Skip to content

Commit

Permalink
Update info
Browse files Browse the repository at this point in the history
  • Loading branch information
frankiesardo committed Feb 19, 2016
1 parent 5d0b611 commit a007c2d
Showing 1 changed file with 25 additions and 26 deletions.
51 changes: 25 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,30 @@ Tripod borrows _(read: shamelessly copy)_ the interceptor chain abstraction and
## What does it look like

```clj
(require '[tripod.core :as tripod :refer [defroutes defhandler])
(require '[tripod.core :as tripod])

(def logged-in "Check user is logged in" ..)
(def same-user "Check logged in user id is same as page requested" ..)
(def logged-in
"Check user is logged in"
..)
(def same-user
"Check logged in user id is same as page requested"
..)

(defhandler home [request]
(defn home [request]
{:status 200 :body "You're home"})

(defhandler view-profile [request]
{:status 200 :body "You're viewing your profile info"})
(defn view-profile [{:keys [path-for] :as request}]
{:status 200 :body (format "Thanks for viewing your profile. You can edit it here %s" (path-for ::edit-profile)})

(defhandler edit-profile [request]
(defn edit-profile [request]
{:status 200 :body "You're editing your profile info"})

(defroutes routes
(def routes
(tripod/expand-routes
[["/" home ^:interceptors [logged-in]
["/users/:id" view-profile
^:constraints {:id #"\d+"} ^:interceptors [same-user]
["/edit" edit-profile]]]])
["/edit" edit-profile]]]]))

(def service
(-> {::tripod/routes routes}
Expand All @@ -38,10 +43,6 @@ Tripod borrows _(read: shamelessly copy)_ the interceptor chain abstraction and

(def ring-handler
(-> service wrap-middleware-1 wrap-middleware-2 ...)))

(def path-for (tripod/path-for-routes routes))

(path-for ::edit-profile {:id 1}) ;;=> "/users/1/edit"
```

Or have a look at a complete example for [ClojureScript](https://github.com/frankiesardo/tripod/blob/master/example/web/src/app/core.cljs) and [Ring](https://github.com/frankiesardo/tripod/blob/master/example/server/src/app/core.clj)
Expand All @@ -54,8 +55,6 @@ Also, sometimes a different way of explaining the same thing might help understa

### Route table

`defroutes` is a convenience macro that calls expand-routes, so equivalent to `(def routes (expand-routes [...]))`

The `expand-routes` function converts a terse nested routes format to a route table.

The terse route format, as shown in the example, consist in a nested vectors structure with:
Expand Down Expand Up @@ -130,11 +129,13 @@ By now you've probably guessed it: a handler is just an interceptor! It usually
(assoc context :response {:foo :bar}))})
```
The use case of getting the request out of the context and associng a response is so common that a helper macro is supplied:
As a convenience functions (and vars) are converted into interceptors that gets the request key out of the context and assoc into it the response.
`(defhandler my-handler [req] (do-something ..) {:foo :bar})`
This way you can use your ring handlers out of the box without changing anything in your code:
Expands to the exact same map as above.
`(defn my-handler [req] (do-something ..) {:foo :bar})`
Is conceptually equivalent to the interceptor map above.
### Context
Expand All @@ -154,22 +155,24 @@ A common example is short-circuiting the execution. In the example above, `logge
:enter (fn [{:keys [request] :as context]
(if (check-session request)
context
(-> context tripod.interceptor/terminate (assoc :response "Nope!"))))})
(-> context tripod.chain/terminate (assoc :response "Nope!"))))})
```
`tripod.interceptor/terminate` removes the remaining interceptors in the execution list.
`tripod.chain/terminate` removes the remaining interceptors in the execution list.
Because there are no more interceptors to execute in the enter stage, the leave stage will start an the error response will be returned.
### Bidirectional
The route table gives us all the information we need to build the path for a route given some params.
A helper function `tripod/path-for-routes` accepts a route table and returns a function that maps route names (namespaced keywords) + params maps to path strings.
A helper function `tripod.path/path-for-routes` accepts a route table and returns a function that maps route names (namespaced keywords) + params maps to path strings.
All the information is readily accessible in the route table and you can build a custom one if you need to.
As a convenience a function `path-for` is added by default into your request map. Also, the function `tripod.core/path-for` is dynamically bound on each incoming request, so you can use that as well.
> As a potential enhancement, path-for can take the currently selected route (e.g. :view-profile) and build a new route (e.g. :edit-profile) without asking explicitly for the :id parameter. Similar to what pedestal already does.
### Service and routing
Expand All @@ -192,7 +195,7 @@ Where:
- `interceptors` is a list of default interceptors that bootstrap the service. Even the routing logic (or any setup logic) can be described by interceptors! These interceptors will be executed before a route is selected.
Tripod default behaviour is added to the map by `tripod/default-interceptors`.
Tripod default behaviour is added to the map by `tripod.core/default-interceptors`.
For a minimal application that's really all you need:
Expand Down Expand Up @@ -231,10 +234,6 @@ Just create them manually and place them in the route table.
- Core.match for exceptions
- Query parameters generation
- Contextual `path-for` (reuse parameters from currently selected route)
- Port the `prefix-tree` router
- Share a routing builder library with pedestal maybe?

0 comments on commit a007c2d

Please sign in to comment.