Simple example of Sandbar or Ring sessions in Google App Engine - google-app-engine

I'm trying to work out how to get sessions and flash working in Google App Engine. Could someone provide a clear example using either Ring or Sandbar? I think I have sandbar working, specifically it doesn't tell me that Var sandbar.stateful-session/sandbar-flash is unbound and when I dump the handler I get :flash and :session though I'm not certain if that is a sandbar session or a ring one. For completeness I will mention that I am using the latest versions of appengine-magic, ring, hiccup and sandbar. There do not appear to be any incompatibilities or issues.
So a clear example preferably with use of flash-put!, flash-get, session-put! and session-get.

I don't usually like answering my own questions, however in this case I'll make an exception because:
a) There isn't a lot of easy to understand examples out there.
b) It would be nice to have a quick working example for others to use.
Note: appengine-magic is not required here, this will also work with normal ring sessions
Code
;; Place in a file called session.clj in the example project
(ns example.session
"Works with the normal ring sessions
allowing you to use side-effects to manage them")
(declare current-session)
(defn wrap-session! [handler]
(fn [request]
(binding [current-session (atom (or (:session request) {}))]
(let [response (handler request)]
(assoc response :session #current-session)))))
(defn session-get
([k] (session-get k nil))
([k default] (if (vector? k)
(get-in #current-session k)
(get #current-session k default))))
(defn session-put!
([m]
(swap! current-session (fn [a b] (merge a m)) m))
([k v]
(swap! current-session (fn [a b] (merge a {k b})) v)))
(defn session-pop! [k]
(let [res (get #current-session k)]
(swap! current-session (fn [a b] (dissoc a b)) k)
res))
(defn session-delete-key! [k]
(swap! current-session (fn [a b] (dissoc a b)) k))
(defn session-destroy! []
(swap! current-session (constantly nil)))
;; Place in a file called core.clj in the example project
(ns example.core
(:use compojure.core
[ring.middleware.keyword-params :only [wrap-keyword-params]]
[ring.middleware.session :only [wrap-session]]
[ring.middleware.session.cookie :only [cookie-store]]
[example session])
(:require [appengine-magic.core :as ae]))
(declare current-session)
(defroutes example-app-routes
(GET "/" _
(fn [req]
(let [counter (session-get :counter 0)]
{:status 200
:headers {"Content-Type" "text/plain"}
:body (str "started: " counter)})))
(GET "/inc" _
(fn [req]
(let [counter (do
(session-put! :counter (inc (session-get :counter 0)))
(session-get :counter))]
{:status 200
:headers {"Content-Type" "text/plain"}
:body (str "incremented: " counter)}))))
(def example-app-handler
(-> #'example-app-routes
wrap-keyword-params
wrap-session!
(wrap-session {:cookie-name "example-app-session"
:store (cookie-store)})))
(ae/def-appengine-app example-app #'example-app-handler)
How to use it
Navigating to http://127.0.0.1:8080/inc increments the counter in the session and http://127.0.0.1:8080/ will display the value of counter in the session.
wrap-session! is not required for sessions to work, just using
(wrap-session {:cookie-name "example-app-session"
:store (cookie-store)})
will give you working functional sessions. However I wanted to manage my sessions with side-effects and wrap-session! provides that functionality. To use flash like functionality, simply use session-put! to put a value into the session and then use session-pop! to remove it.
Hope that's helpful.

If you want to use the Sessions provided by GAE, you can use the following
https://gist.github.com/1095841
to include a ring like session in your requests, but based on GAE session support.
If you want stateful sessions on top of this, you can use the stateful session API provided by Sandbar
https://github.com/brentonashworth/sandbar

Related

ReactTestUtils.Simulate.mouseDown

I'm trying to use the React Simulate function to simulate a mouseDown event for testing.
(defn mouse-down [node]
((.-mouseDown(.-Simulate ReactTestUtils) node (clj->js {:button 0})))
js translation:
ReactTestUtils.Simulate.mouseDown(node, {button: 0})
Nothing I've tried has resulted in an invocation of the mousedown listener--but when the listener is there when i try it in the browser where it works. It's just in the simulation.
What am I missing?
There are a couple mistakes in the Syntax here and your parens don't match. Generally it becomes easier if you reorganize the code a bit and -> can help there. As mentioned in the comment you want to use .mouseDown instead of .-mouseDown. I opted to use #js instead of clj->js since that is more optimal for static js objects such as this.
(defn mouse-down [node]
(-> (.-Simulate ReactTestUtils)
(.mouseDown node #js {:button 0})))
You can also make this a little more readable depending on where ReactTestUtils is coming from. I'm assuming its from the react-dom package which you just required.
;; in your ns
(:require ["react-dom/test-utils" :as ReactTestUtils])
;; which would allow
(defn mouse-down [node]
(ReactTestUtils/Simulate.mouseDown node #js {:button 0}))
;; or if you are on the latest CLJS version
(:require ["react-dom/test-utils$Simulate" :as sim])
;; and then
(defn mouse-down [node]
(sim/mouseDown node #js {:button 0}))

CommonLisp Function for dynamically looking up bindings in packages

Is there a way to dynamically ask for bindings in another package, and by dynamically i mean by not knowing the exact name of a binding in some package. A concrete case would be:
As in package B, i know there exists a package A which has a certain class and i extract all direct slots of that class by (in LispWorks):
(setq direct-slots (mapcar #'slot-definition-name
(class-direct-slots (class-of class-in-package-A))))
Now i want to bind those slots to some values using MAPCAR:
(mapcar #'(lambda (slot) (list slot
(funcall slot class-in-package-A)))
direct-slots)
This doesn't work since i am in package B and need package precision for the call to (funcall slot class-in-package-A), packageA::slot is obviously wrong. Is there a function for this which searchs for a certain symbol in a package?
If you have a slot-name and want to get the value of the named slot in some object, use slot-value:
(mapcar (lambda (slot-name)
(slot-value some-object slot-name))
slot-names)
Slot names are symbols, and they will not magically lose their package if you happen to “be” in a different package. I think your confusion is that you are thinking about accessors, but those are a different thing (they use something like slot-value internally).
CL-USER> (defpackage #:foo
(:use #:cl))
#<PACKAGE "FOO">
CL-USER> (defpackage #:bar
(:use #:cl #:sb-mop)) ; in SBCL
#<PACKAGE "BAR">
CL-USER> (in-package #:foo)
#<PACKAGE "FOO">
FOO> (defclass afoo ()
((a :initarg :a)
(b :initarg :b)))
#<STANDARD-CLASS FOO::AFOO>
FOO> (in-package #:bar)
#<PACKAGE "BAR">
BAR> (mapcar #'slot-definition-name
(class-direct-slots (find-class 'foo::afoo)))
(FOO::A FOO::B)
BAR> (let ((slot-names (mapcar #'slot-definition-name
(class-direct-slots (find-class 'foo::afoo))))
(obj (make-instance 'foo::afoo
:a 1
:b 2)))
(mapcar (lambda (slot-name)
(slot-value obj slot-name))
slot-names))
(1 2)
In general, you should be using accessors in “user” code, and you should know which accessors exist for a given object. It also shouldn't matter for user code whether something is a direct slot.

In clojurescript, how to evaluate a list

Suppose having
(def defining-list `(def one 1))
How can I evaluate defining-list so that one becomes 1 ?
(in clojurescript)
EDIT:
I will give an idea of the broader image and what I am trying to accomplish here to avoid falling into an X/y problem.
I am trying to use cljsjs/material-ui from cljsjs package
Instead of defining each time a react component to use it as following:
(def app-bar
(r/adapt-react-class (aget js/MaterialUI (name :AppBar)))
I would like to define all the components from an array of tags:
(def material-ui-tags '[AppBar Avatar Backdrop])
So I was thinking if it's possible to do this without the usage of a macro as I found this
Something like:
(doseq [component material-ui-tags]
`(def ~(symbol (->kebab-case component)) (r/adapt-react-class (aget js/MaterialUI ~(name component)))))
But the above does only create a list of defs, I would like to evaluate these. In clojure eval would do the trick.
With reagent, you can use :> as shorthand for adapt-react-class as documented in https://github.com/reagent-project/reagent/blob/master/docs/InteropWithReact.md
Also, you can use dot notation with js/ and I think in shadow-cljs or cljs above 1.9.854 you can require to import the symbol instead of using aget.
In your case, it would be something like:
(ns example.core
(:require [MaterialUI]))
(defn component-two []
[:> MaterialUI/AppBar {:some-prop "some-value"}
[:div "children-here"]])
(defn component-two []
;; If the require above doesn't work
[:> js/MaterialUI.AppBar {:some-prop "some-value"}
[:div "children-here"]])
To do what you wanted using def, you either need eval or macro. Eval is not ideal as Jared Smith explained in the comment.
The example that you linked from reagent-material-ui uses macro. Invoking a macro actually performs expansion and then evaluation. So your code needs to be something like this:
clj file
(def material-ui-tags '[AppBar Avatar Backdrop])
(defmacro adapt-components []
(for [component material-ui-tags]
`(def ~(symbol (->kebab-case component)) (reagent.core/adapt-react-class (aget js/MaterialUI ~(name component))))))
cljs file
(adapt-components) ;; your defs will be available below this line
(defn my-component []
[app-bar ...])

Applying macros in other namespace

I have file with dsl-like stuff data. There I want to declore some s-expression based information. And I have some runner that process such files.
runner.clj
(require '[data :as d])
;processing
data.clj
(ns data)
(defmacro data [s] (println (str s)))
;dsl like stuff goes here
(data "foo")
How can I remove non dsl from data file like defmacro?
Also any links to source code with similar solutions are welcome.
; dsl.clj
(ns dsl)
(defmacro data ...)
; data.clj
(ns data
(:require dsl))
(dsl/data ...)
Or with use:
; data.clj
(ns data
(:use [dsl :only (data)]))
(data ...)

Issues with getting both POST and GET http parameters in appengine-magic 0.4.3/Compojure 0.6.4

I'm having some serious issues with capturing POST and GET parameters with the latest appengine-magic/compojure versions. The parameters always come up as blank, even though the request object clearly has the right stuff in it.
I've seen some stuff around the interwebs about a change in the Compojure protocol where you have to manually put in the wrappers. I've tried this (using the handler/api wrapper to avoid the stuff in handler/site wrapper that breaks GAE) but it still doesn't work.
What am I doing wrong here?
My project.clj file:
(defproject pitch-filter "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[compojure "0.6.4"]
[hiccup "0.3.6"]
[jtidy "4aug2000r7-dev"]
[commons-lang "2.5"]]
:dev-dependencies [[appengine-magic "0.4.2"]
[clj-http "0.1.1"]])
My core.clj file:
(ns pitch-filter.core
(:use compojure.core
[appengine-magic.multipart-params :only [wrap-multipart-params]]
[hiccup.middleware :only (wrap-base-url)])
(:require [pitch-filter.fetch :as fetch]
[compojure.route :as route]
[compojure.handler :as handler]
[appengine-magic.core :as ae]
[appengine-magic.services.url-fetch :as url]
(defroutes pitch-filter-app-routes
(GET "/" [] "Main Page")
(GET "/form" []
(str "<form method='post' action='/post'>"
"<input type='text' name='test'>"
"<input type='submit'>"
"</form>"))
(POST "/post" {params :params}
(pr-str params))
(route/not-found "Page not found"))
(def pitch-filter-app-handler
(-> pitch-filter-app-routes
(handler/api)
(wrap-base-url)
))
(ae/def-appengine-app pitch-filter-app #'pitch-filter-app-handler)
It certainly looks like dev_appserver.sh is busted with App Engine 1.5.1. Pity, but you aren't really supposed to use it with appengine-magic. You should use the interactive REPL tools (i.e., ae/serve). They work fine.
I updated the ticket you opened on the appengine-magic project page (https://github.com/gcv/appengine-magic/issues/28).
-gcv
Turns out that this issue only happens when using the Google App Engine 1.5.1 dev_appserver.sh. It works fine with 1.4.3. I'll leave this open in case someone else finds a better solution.

Resources