On 8 January 2015 at 15:10, Malcolm Sparks <[email protected]> wrote:
>
> The idea here is that you want individual components to be able to
> 'contribute' groups of routes. That way, you can avoid the common practice
> of having one big 'god' namespace containing all the Ring routes, which is
> then tightly coupled to all your Ring handlers. Instead, it's nice to have
> the flexibility to compose systems from different combinations of
> components.
>
> One implementation approach is to have a 'router' component that delegates
> to its dependencies. That way, routes can be 'plugged in' using dependency
> declarations.
>
> Currently I only implemented this with bidi, which I'm slightly biased
> towards (because I wrote it). My 'router' implementation is here:
> https://github.com/juxt/modular/blob/master/modules/bidi/src/modular/bidi.clj
>
That's an interesting setup. Are you merging the data-driven bidi routes
together?
If I may, let me run past you an idea I've been experimenting with that has
a similar goal.
I've been using functions that take in a configuration map (in practice, a
component) and return a handler. I call these "endpoints" (highly original,
I know).
(defn hello-endpoint [config]
(fn [request]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello World"}))
Wrapping endpoints in a component is relatively straightforward:
https://github.com/weavejester/duct/blob/master/duct/src/duct/component/endpoint.clj
In Duct, the template/framework I'm designing, I use the Compojure
mechanism of trying endpoints in turn until one returns a non-nil value.
However, one could quite easily write a routing mechanism that dispatches
on a context path, or a regular expression.
This approach is pretty minimal, but has a few advantages:
1. It's not tied to a particular routing library
2. It's a simple interface
3. Configuration is passed down via a closure & destructuring
As a more practical example, consider an endpoint that relies on a database
connection:
(defn product-endpoint [{db :db}]
(routes
(GET "/" [] (list-products db)
(POST "/" [product] (add-product db product))
(GET "/:id" [id] (find-product db id))))
When we come to write our system, we wrap the endpoint in a component, and
have it depend upon the database component:
(defn new-system [config]
(-> (component/system-map
:db (database (:db config))
:product (endpoint-component product-endpoint))
(component/system-using
{:product [:db]}))
(In the above example I've omitted the component that combines all the
endpoints together into a handler, as I think that's a more opinionated
component.)
Do you think this "endpoint" approach could work in Modular? I like the
idea of having a standard way of defining a subset of routes that depend on
a configuration.
- James
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.