James Reeves Appreciation Day

9 views
Skip to first unread message
Message has been deleted

Sean

unread,
Mar 21, 2009, 3:36:00 PM3/21/09
to Compojure
Thanks a lot! We should have our own James Reeves appreciation day :)

On Mar 21, 3:23 pm, James Reeves <weavejes...@googlemail.com> wrote:
> Hi folks,
>
> I've just finished making some large changes to the Compojure
> repository. Read on for a breakdown of the new additions:
>
> == Version 0.1 released ==
>
> I've taken the current code that people have been using, and forked it
> into the "stable" branch. People have been using this with fairly few
> problems reported, so I've released this as version 0.1. This version
> uses the tried-and-tested "defservlet" syntax most people are familiar
> with.
>
> == Ring branch merged ==
>
> The "ring" branch has now been merged into the master branch. This
> represents a big change to how Compojure is put together, with a few
> changes to the syntax. Note that this hasn't been used as extensively
> as version 0.1, so you might run into bugs that have been missed out
> during testing. I'll try and fix any reported issue as quickly as
> possible.
>
> = defroutes syntax =
>
> Instead of using defservlet to define a servlet, you now should use
> defroutes:
>
>   (defroutes my-app
>     (GET "/"
>       (html [:h1 "Hello World"])))
>
> This defines a Ring handler. This is a function that takes in a
> request map, and returns a response map:
>
>   => (my-app {:request-method :get, :uri "/"})
>   {:status 200, :headers {}, :body "<h1>Hello World</h1>"}
>
> With this syntax, Compojure achieves a great deal of flexibility. You
> can simply define middleware functions to handle caching, and easily
> write interfaces to plug Compojure into any web server you wish. It's
> also a heck of a lot easier to test.
>
> Read more about how the request and response map are defined in the
> Ring SPEC:
>
> http://github.com/mmcgrana/ring/blob/4a035a2c20c654cf8020379aad8625e2...
>
> Once you've applied all your middleware to your routes, you can turn
> it into a servlet with the 'servlet' inline:
>
>   (run-server {:port 8080}
>     "/*" (servlet my-app))
>
> Or use the defservice macro to create a "-service" function, suitable
> for genclass:
>
>   (defservice my-app)
>
> No longer is there a need for messy hacks to abstract your routes from
> their implementation. But it gets even better; because defservice and
> servlet are macros and inlines respectively, if you redefine your
> routes, any changes you make will automatically and instantly be
> picked up.
>
> = Embedding routes =
>
> You can also embed routes inside routes. This is useful if you have a
> whole bunch of routes and you want to split them up into logical
> sections:
>
>   (defroutes all-routes
>     (GET "/admin/*"
>       admin-routes)
>     (GET "/*"
>       public-routes))
>
> = Returning headers =
>
> Compojure now treats any map being returned by a route as a response
> map. This means that adding headers is a little more verbose:
>
>   (GET "/"
>     [{:headers {"Content-Type" "text/plain"}}
>      "Hello World"])
>
> Or alternatively:
>
>   (GET "/"
>     {:headers {"Content-Type" "text/plain"}
>      :body    "Hello World"})
>
> = Route local bindings =
>
> There are now only five local bindings defined for each route:
>
> * request - the request map
> * params  - a map of all the parameters in the request
> * cookies - the cookies in the request
> * session - the request session
> * flash   - the session flash
>
> This seems bare, but that's because a lot of information is now stored
> in the request map. Along with all the keys mentioned in Mark's Ring
> SPEC file, such as :uri and :request-method, Compojure adds the
> following additional keys:
>
> * :route-params - parameters matched by the route
> * :query-params - parameters encoded in the query string
> * :form-params  - parameters encoded in the request body
> * :cookies      - the cookies in the request
> * :session      - the request session
> * :flash        - the session flash
>
> Basically, all the information you could ever want is now stored in
> the request map. The local bindings just provide convenient shortcuts.
>
> = Sessions =
>
> Sessions are now completely detached from Java. They're functional and
> easily extensible, so you can store your sessions in files, in a
> database, or wherever you wish, just by overriding a few multimethods.
> Compojure defaults to using in-memory sessions, and this is currently
> the only type of session included with Compojure.
>
> To read from sessions, you can use the session binding:
>
>   (GET "/"
>     (html [:h1 "User: " (session :user)]))
>
> To write a session you can return the session in the response map:
>
>   (POST "/"
>     [{:session (assoc session :user (params :user))}
>      (redirect-to "/")])
>
> That's a little long-winded though, so you can use the session-assoc
> and session-dissoc functions to make it easier:
>
>   (POST "/"
>     [(session-assoc :user (params :user))
>      (redirect-to "/")])
>
> The session-assoc and session-dissoc demonstrate functionality related
> to embedded routes. Because routes are just functions, you can return
> your own handler functions from routes:
>
>   (POST "/"
>     (fn [request]
>       {:session (assoc (request :session) :user (params :user))}))
>
> This is why session-assoc can functionally modify the session without
> needing to be passed the session explicitly.
>
> = Flash =
>
> The flash is a place to store temporary messages between requests.
> Anything added to (session :flash) will persist until the next
> request, then be wiped. For example:
>
>   (POST "/register"
>     [(flash-assoc :message "Set username")
>      (session-assoc :user (params :user))
>      (redirect-to "/")])
>   (GET "/"
>     (html
>       (if (flash :message)
>         [:div.message (flash :message)])
>       ...))
>
> = Upcoming features =
>
> That's about it for the current changes. I'll briefly mention what I'm
> looking to have in Compojure in the near future:
>
> * Session storage types of :cookie and :file
> * File uploads
> * SSL support in Jetty server
> * Possibly a Grizzly server
> * Absolute URL support in routes so you can set subdomains:
>
>   (GET "http://:category.example.com/"
>     (index (params :category)))
>
> - James

radu.floricica

unread,
Mar 21, 2009, 7:27:41 PM3/21/09
to Compojure

Hip Hip Hurraay!

Turns out to be a pretty nice spring.

James Reeves

unread,
Mar 21, 2009, 7:37:09 PM3/21/09
to Compojure
On Mar 21, 7:36 pm, Sean <francoisdev...@gmail.com> wrote:
> Thanks a lot!  We should have our own James Reeves appreciation day :)

You should save your thanks until after all the bugs are weeded out
from this release ;)

Also, I built my current changes on top of Mark McGranaghan's work on
Ring. Mark's Ring specification is simple and elegant, and a lot of
the advantages of the new branch are due to the flexibility of his
approach.

(Still, it's nice to be appreciated!)

- James

Adrian Cuthbertson

unread,
Mar 22, 2009, 1:28:47 AM3/22/09
to comp...@googlegroups.com
This is awesome James - here comes clojure's killer app!
> http://github.com/mmcgrana/ring/blob/4a035a2c20c654cf8020379aad8625e2c899d4f0/SPEC
Reply all
Reply to author
Forward
0 new messages