This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # admin-announcements (14)
- # architecture (1)
- # beginners (21)
- # boot (301)
- # clojure (93)
- # clojure-brasil (56)
- # clojure-india (4)
- # clojure-italy (11)
- # clojure-japan (25)
- # clojure-russia (16)
- # clojure-sg (1)
- # clojure-uk (5)
- # clojurescript (64)
- # clojurex (4)
- # clojutre (7)
- # cursive (18)
- # datascript (35)
- # datomic (212)
- # editors (27)
- # emacs (38)
- # events (9)
- # funcool (21)
- # hoplon (105)
- # jobs (2)
- # ldnclj (41)
- # ldnproclodo (4)
- # liberator (89)
- # luminus (5)
- # off-topic (32)
- # om (39)
- # onyx (1)
- # re-frame (9)
- # reactive (1)
- # reagent (34)
- # testing (42)
- # yada (4)
I'm trying to use Bidi with liberator and Enlive and have a small problem with circular dependencies...
Basically I want to use
bidi.bidi/path-for to generate a route definition in one of my resources - but doing so will introduce a circular dependency as
path-for needs access to my
routes but I can't do this because my routes depend on my resources and my resources depend on my pages (enlive templates).
These are currently split into three namespaces, so i can't really use a
declare here... How do people normally factor their routes/resources/pages to avoid this?
It seems this circular dependency is implied for routes to be bidirectional, was wondering if bidi could possibly augment the request with the routes map
One way is to bind your
routes to a future and use that from within your handlers.
I, personally, use component and co-dependencies from the modular lilbs: https://github.com/juxt/modular.co-dependency/
It allows you to specify deps and co-deps in your system (I have a routes-provider component). The co-deps are resolved via deref and allow circular deps.
> The penalty for not understanding this point is days spent figuring out why you can't see a co-dependency's data. It's because you're still trying to access this data within the start phase of your component. Don't do this. Defer the lookup until after the entire start phase of your system has completed.
regarding the promise pattern: https://github.com/juxt/bidi/blob/master/doc/patterns.md
With bidi you can use tagged routes, so you only need to pass around a promis that contains the
Or you can bind your routes to the request, at
:routes and should be able to avoid promises at all. *thinking*
I guess I could put a middleware in that would bind them after the routes were loaded
yeah its pretty simple - but means every page will need to have the parameter passed to it
yeah I know -- just each resource will need to destructure the routes from the ctx and either do the
path-for or pass the routes to the enlive templates to do it
I see. You can always use a dynamic var if that bugs you. And a function that accesses it.
(def :^private :^dynamic current-routes nil) (defn path-for [& args] (apply bidi/path-for current-routes args)) ;; and a middleware (defn wrap-bind-routes [h routes] (fn [req] (binding [current-routes routes] (h req))))
path-for is a little suggar enabling
(path-for ::user :id „some-user“) and you can omit the routes altogether
Not sure, however, how this would compose for nested route definitions when you have multiple subsystem that offer routes which you would mount together.
In this case, when you consider the routes a global thing (like you would with the promises) they come in handy. But testing can be a pain.
might do that after all - as in this case they're not going to change post initialisation... Thanks for talking this through with me... it was useful
@rickmoynihan: this circular dependency problem comes up occasionally, that's what co-dependency tries to help with - in this case the circular dependency is hard to get round, it's at the very core of the web's design - URIs identify resources, resources produces representations, representations should contain URIs, which identify resources ....
if you're into hypermedia APIs that is, and that's what bidi is really built to support
co-dependency looks interesting -- but seems like overkill for just this -- though I have been looking at introducing component at some point
fwiw, I use co-dependency so that components that contain routable resources can also capture, via lexical scope, the overall 'routes' that each resource might need to produce representations that contain URIs
@rickmoynihan: ah, I'd only recommend co-dependency if you're already using component, if you aren't then use another approach like a promise
co-dependency is designed to workaround the fact that component enforces an ADT
I actually use a notation for derefables (promises, futures, refs), a star prefix
@malcolmsparks: was meaning to ask you -- I recently looked at yada which looks really quite nice.... I especially like the liberator style + swagger... however I eventually chose liberator because it seemed like yada was still in flux and is less mature... Is that a fair assessment? Should I have chosen yada yet?
oh yes, that's right. yada is very much a work-in-progress - it isn't ready for production use
I suggest use a function
path-for which uses and derefs the global promise of the routes.
one thing to bear in mind is that bidi's path-for can be a little slow (compared to dispatch, which has been heavily tuned)
I've been talking with a co-contributor about creating an index, but until then I suggest you memoize if performance is critical
bidi must walk its tree each time - but we could easily create an index to speed it up, just haven't got round to it yet
(declare routes) (defn path-for [tag & args] (apply bidi/path-for @routes tag args)) (defresource foo  :handle-ok (fn [ctx] (path-for ::bar))) (defresource bar  :handle-ok (fn [ctx] (path-for ::foo))) (def routes (promise [/ [[„this-is-foo“ (tag foo ::foo)] [„this-is-bar“ (tag bar ::bar)]]]))
@rickmoynihan: I’ve seen people doing it but I don’t know of a general solution
@malcolmsparks: yes, I think memoize would be the way to go. the promise contains a static route definition in the end.
the problem with doing swagger in liberator, generally speaking, is that liberator is based around boolean answers to questions - true, true, false, true, false, etc..
you can use a swagger data model, though, and use that to declare your liberator resources.
or use your own data model and derive swagger and the liberator resource declaration from it.
yada is trying to help those who really can't be bothered to do all that just to get swagger output
lol - well I don't care for swagger as such... more just that I want the automatic doc generation and test ui
@ordnungswidrig: FYI you can't use
promise like that (its a arity 0) - I think we actually need a
@rickmoynihan: oh, sorry, yes. that should’ve been
(def routes (promise)) and
(deliver routes […])
@ordnungswidrig: yeah it would be useful - bidi's main selling point is moot without having a solution to this
Does bidi have anything for assembling query string parameters? Or do I just need to str them on myself?