One shouldn't have to ask this here, but thanks to the bad documentation, how do I access the querystring in a Spiffy (egg) app? Thanks!
(use intarweb spiffy sxml-serializer)
(tcp-buffer-size 2048)
(server-port 80)
(handle-not-found (lambda (path)
; (print (request-uri (current-request)))
; (print (request-method (current-request)))
; (print (current-pathinfo (current-request)))
; (print (current-file))
; (print (remote-address))
(send-response
body: (serialize-sxml
`(div (# (class "page"))
(h1 ,path))
method: 'html))))
(start-server)
I'm not exactly sure why you want to access the query string, but the
URI objects in Spiffy come from the request object, as you've correctly
identified. The request object is from intarweb, which sticks an
uri-common object in the request-uri attribute.
You can access the constituent component parts using uri-common's
accessors, as documented in the URI-common egg reference
The query string is parsed into an alist for your convenience, and
accessible through (uri-query (request-uri (current-request))).
The "original" query string can be accessed a little more differently:
the uri-common egg is a convenience wrapper around the lower-level egg
uri-generic, which you can access by calling (uri->uri-generic URI),
where URI is (request-uri (current-request)), as before.
Then, you can access the query string through the uri-query procedure
from that egg. Here's a simple example you can use on the REPL:
#;1> (use uri-common (prefix uri-generic generic:))
#;2> (uri-reference "http://foo?x=y")
#<URI-common: scheme=http port=#f host="foo" path=() query=((x . "y")) fragment=#f>
#;3> (uri-query #2)
((x . "y"))
#;4> (uri->uri-generic #2)
#<<URI>>
#;5> (generic:uri-query #4)
"x=y"
What I did here is prefix all the procedures from uri-generic with
"generic:". This is necessary because uri-common "shadows" all the
procedures defined by uri-generic.
Related
I want to implement caching of api in clojure, In my application I have api's which are called for some of the functionalities. I want to reduce that api calls. I want to use clojure.core.cache.wrapped which is implemented upon clojure.core.cache. I want to cache my api call response base on the url.
The url is GET and has query inside the url that differentiates the response
for eg
http://localhost:3000/:clientid/get_data
Sample code
(:require [clojure-mauth-client.request :refer [get!]]
[clojure.core.cache.wrapped :as cw])
(def my-cache (cw/ttl-cache-factory {} :ttl 60000))
(defn get-data-caller [cid]
(cw/lookup-or-miss my-cache cid get-data))
(defn get-data [cid]
(let [req-url (str "/api/get-data?id=" cid)
response (retry-request (sign-credentials #(get! base-url req-url)) 3)]
(println response))))
I want to implement in a way that it caches depending on the cid.
In above code 3 is max-retries
With current implementation I am getting below error.
In my current code it is calling the api again and again
I got the solution, The main mistake I made here is that I implemented this in
get-data-caller
lookup-or-miss actually accepts 3 params
lookup-or-miss [cache key fn]
Here
1. cache is the one that we create.
2. key that we want to use as 'key' in our caching
3. The third has to be the function, that takes 'key' as an arg and gets data for us.
So lookup-or-miss will first check if the we have cached data for the 'key' passed, if not then, that will be passed as an arg to the third arg (i.e the fn) and get the fresh data.
If the cache data is not present for the key, then the fn in the third arg will be called with key as arg to get the data.
With above understanding I did rewrite my code as below
(:require [clojure-mauth-client.request :refer [get!]]
[clojure.core.cache.wrapped :as cw])
(def my-cache (cw/ttl-cache-factory {} :ttl 60000))
(defn http
[url]
(retry-request (sign-credentials #(get! url)) 3))
(defn get-data-caller [cid]
(get-data cid))
(defn get-data [cid]
(let [req-url (str "/api/get-data?id=" cid)
response (cw/lookup-or-miss my-cache req-url http-request)]
(println response))))
So here lookup-or-miss will search req-url key in my-cache, if present it will directly return the value stored, if not then it will call http-request with req-url as an arg
So lookup-or-miss will be executed something like this;
pseudo code for understanding
(if (contains? my-cache req-url)
(:req-url my-cache)
(http-request req-url))
I have an array of users, each with its own locale.
I need to get a translation of the message into the language of each user.
...
Enum.map(user.tokens, fn(t) -> t.token end)
|> Sender.send(translated_msg(user.locale, msg))
...
defp translated_msg(locale, msg) do
message = Gettext.with_locale MyApp.Gettext, locale, fn ->
MyApp.Gettext.gettext(msg.body, msg.bindings)
end
message
end
where
msg = %{body: "%{login} added a new operation", bindings: %{login: current_user.login}}
But such code is not compiled
== Compilation error on file web/helpers/sender_helper.ex ==
** (ArgumentError) *gettext macros expect translation keys (msgid and msgid_plural) and
domains to expand to strings at compile-time, but the given msgid
doesn't.
Dynamic translations should be avoided as they limit gettext's
ability to extract translations from your source code. If you are
sure you need dynamic lookup, you can use the functions in the Gettext
module:
string = "hello world"
Gettext.gettext(MyApp.Gettext, string)
(gettext) lib/gettext/compiler.ex:196: anonymous fn/2 in Gettext.Compiler.expand_to_binary/4
expanding macro: MyApp.Gettext.dgettext_noop/2
web/helpers/push_helper.ex:23: MyApp.SenderHelper.translated_msg/2
expanding macro: MyApp.Gettext.dgettext/3
web/helpers/push_helper.ex:23: MyApp.SenderHelper.translated_msg/2
expanding macro: MyApp.Gettext.gettext/1
web/helpers/push_helper.ex:23: MyApp.SenderHelper.translated_msg/2
(elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
How can I manually translate a message into another language?
Just like the error message says, if the string to translate is dynamic, you need to use Gettext.gettext/{2,3} passing in your app's Gettext module as the first argument. Since you're passing bindings as well, you need to use Gettext.gettext/3:
Gettext.gettext(MyApp.Gettext, msg.body, msg.bindings)
I am doing an Ajax GET from my Reagent application, to load some stuff from the database.
I am not entirely sure what is the best way of getting the result of such ajax call to my page, considering that if I put it in an atom, then Reagent automatically re-renders a component when an atom is dereferenced, which means I get an infinite sequence of ajax calls.
For some code,
(def matches (atom nil))
(defn render-matches [ms]
(reset! matches (into [:ul] (map (fn [m] ^{:key m}[:li m])
(walk/keywordize-keys (t/read (t/reader :json) ms)))))
This function basically creates a [:ul [:li "Stuff here"] [:li "And here"]]
Which i would like displayed on my page, which now has the following code.
(defn standings-page []
(GET "/list-matches"
{:handler render-matches})
#matches)
I think it's better to save only data in an atom and to generate the HTML as part of the component logic.
Also it's better to trigger the AJAX call outside the render phase, for example, before the component will mount, or as the result of an event (on-click on a button for example).
Like this:
(def matches (atom nil))
(defn component []
(let [get-stuff (fn [] (GET "/..." :handler (fn [response]
(reset! matches (:body response))))]
(get-stuff) <-- called before component mount
(fn []
[:ul
(for [m match]
^{:key ...}
[:li ...])])))
This is called form-2 in this post.
I have a two mailers
welcome_manger(user) welcome_participant(user)
Both send different information and have different layouts.
when I call the deliver method I would like to use something like the following
UserMailer.welcome_self.role(self.user)
This does not work. How can I accomplish this?
Something like this perhaps:
m = 'welcome_' + self.role
UserMailer.send(m.to_sym, [self.user])
Assuming that self.role returns a String.
The send method invokes a method by name:
obj.send(symbol [, args...]) → obj
Invokes the method identified by symbol, passing it any arguments specified.
So you just need to build the appropriate method name as a string and then convert it a symbol with to_sym.
seems like a call to
$this->_redirect('*/*/myaction',$myargs);
does not properly escape the arguments
so if
$myargs=array(p1=>'string that has + or / within it')
the created URL will be something like:
..../myaction/?p1/string%20that%20has%20+%20or%20/%20within%20it
causing the getParams collection on the action to have
p1 with value 'string that has or ' <- plus sign missing and value broken and
' within it' with no value or something similar.
is there any standard way I should handle the arguments before passing them to _redirect ?
Eyal
Yes, there are two standard ways.
Pass all your params as route params, but encode them with php urlencode() func:
foreach ($myargs as $key => $val) {
$myargs[$key] = urlencode($val);
}
$this->_redirect('*/*/myaction', $myargs);
Pass your params as query params
$this->_redirect('*/*/myaction', array('_query', $myargs));
You'd better take second approach, because your params logically are not route but query parameters. Magento is made with a lot of architecture thinking, so it usually points better ways to do stuff - that's why in your case it's easier to send params using second way.
Notice: _redirect() internally uses Mage_Core_Model_Url, so everything said in this answer is true for all other url-forming routines and all usages of Url model.
refer to http://www.blooberry.com/indexdot/html/topics/urlencoding.htm#whatwhy and read the section "Reserved characters"