Being new to clojure, I would like some advice on implementing the repository pattern*.
In an OO language, I would create a repository interface, a test and at least one db impl. I would instantiate them during bootstrap, pass the objects around using DI or get them through a service locator. I'm guessing it's done completely different in clojure?
1) What is a good way of grouping the functions in the repo? Protocol, "free" functions in a namespace?
2) Where do I instantiate the repository back-end, i.e. allocate resources like db-connections etc.? Do I instantiate an implementation of the repository protocol and assign it to an atom, or in the case of free functions, redefine them?
*) A repository is a back-end abstraction for persistence and typically supports a CRUD style range of operations.
EDIT: Here is the approach I'm currently using. A protocol to group functions. A test and a "real" record implementing it. Then an atom to register the repo with.
(defprotocol GardenRepo
"Repository of Gardens. Supports CRUD style operations."
(list-gardens [repo] "Get a seq of all gardens in the repo.")
(get-garden [repo id] "Get a specific garden by it's id.")
...)
(let [repo (atom nil)]
(defn get-garden-repo [] #locator)
(defn set-garden-repo [new-repo] (reset! repo new-repo)))
1) Group functions by shared subproblems. In our ORM we have a namespace for db interaction, a separate namespace for each target db, a namespace for model construction and query operations, a namespace for field definition, a separate namespace describing each implementation of the field protocol (ie. int, string, text, slug, collection).
2) Use a function that returns all the functions used, each implicitly using resources defined by the passed in config, ie.:
(defn make-repository
[config]
(let [db (initialize-db config)
cleanup #(do-cleanup db)
store (fn [key val] (store-data key val db))
retrieve (fn [key] (retrieve-data key db))]
{:db db ;; this is optional, can be very useful during initial development
:cleanup cleanup
:store store
:retrieve retrieve}))
This could of course create an instance of a record if access of the functions is a performance bottleneck, and the record could implement a protocol if you want to define multiple implementations of the same functionality (different db drivers that may need different setup etc.). The user of the library decides how and where to bind these functions you return, as appropriate for their own design.
An example of how a client could use this repository:
(def repo (make-repository config))
(def cleanup-repo (:cleanup repo))
(def store-to-repo (:store repo))
(def retrieve-from-repo (:retrieve repo))
(defn store-item
[data]
(let [processed (process data)
key (generate-key data)]
(try (store-to-repo key data)
(catch Exception e
(cleanup-repo)))))
Related
How do I intitailze my database so my (def db ...) will not attempt to initialize the database when running my unit-tests (since it will not be a database there then).
I mock the the sql and dml in functions (with-redefs) but all examples i have found so far simply define the database directly in the namespace (eg not wrapped in a function).
I strongly recommend you do not put your database in a Var. It's a very tempting, but quite harmful, form of environment coupling.
The recommended way is to pass the database your database as an argument of whatever function needs access to it in its body:
;; BAD
(def db ...)
(defn find-user [user-id]
(run-query find-user-query db user-id))
;; GOOD
(defn find-user [db user-id]
(run-query find-user-query db user-id))
It's not as tedious as you'd think, and the benefits are great (for testing, repl-driven development, etc.).
NOTE:
In the early years of the Clojure community, people have been using dynamic Vars to avoid having to add a parameter all the time.
(def ^:dynamic db nil)
(binding [db ...]
(find-user user-id))
Then we learned to stop doing that :) complecting your logic with its environment is just a bad foundation for your programs.
How can I list all the routes on a handler function? I'm looking for behavior similar to rails' rake routes. For example:
(defroutes foo-routes
(GET "/foo/:foo-id"
[foo-id]
"bar response")
(GET "/bar/:bar-id"
[bar-id]
"foo response"))
Is it then possible to extract a map from foo-bar-routes containing the following?
{:GET "/foo/:foo-id"
:GET "/bar/:bar-id"}
I don't think it is possible. defroutes is a macro that returns a ring handler. GET is a macro that returns a route. Route is again just a function that calls related handler only if method and path are matching. So in the end your foo-routes is just a clojure function that is composed of other functions defined by your routes and it doesn't maintain such map. If you need to get such map, maybe you can maintain it in your code yourself and generate routes out of this map.
I know this thread is quite old but I had the same question and could resolve it by myself, here's what I've got:
Assuming you defined your API this way:
(def my-api (compojure.api.api/api ...))
Then you can easily list the routes you defined that way:
(->> (.-get-routes my-api {})
(map (juxt second first)))
I am trying to write Webdriver checks using Clojure. If I was using an object oriented language, I would use the Page Object Pattern. I think modeling a page as an object makes sense, I could create some java classes for the page objects and all would be well.
I want to know if there are any alternatives to the page object pattern using a functional style that maintain the same level of clarity.
A page (especially a RESTful one), can be thought of as a function from request to render (and, if you want to take the next step, the render exposes some set of new requests).
The translation from sending a request to page to applying a function to arguments is simple, and also quite comprehensive.
If you are providing a complex webapp, try taking a functional view of requests. GET can retrieve data, but should not modify server side state, use PUT to create a resource, use POST for mutation.
Once you write your controllers in this way, you can do quite a bit of testing without webdrivers. It should mostly suffice to provide a mockup of the request input to the controller, and verify some properties of the rendered result (for GET) or the storage state (for POST AND PUT).
I have even found it useful to break off request parsing and rendering into separate functions, in order to simplify the testing of the data processing that should happen in the middle, ie.:
(defn parse-home
[request]
(let [user-id (-> request :params :session :id)
account (get-user user-id)]
{:user-id user-id
:account account}))
(defn do-home
[user-id account]
(let [messages (get-messages account)
feed (generate-feed user-id)]
(update-user user-id :last-visited (java.util.Date.))
{:messages messages
:feed feed}))
(defn render-home
[request messages feed account]
(let [messages (mapv summarize (filter important messages))
feed (sort-by :priority feed)
template (-> request :page :template)]
(render template (assoc request :data {:messages messages :feed feed :account account}))))
(defn home
[request]
(let [{:keys [user-id account]} (parse-home request)
{:keys [messages feed]} (do-home user-id account)
body (render-home request messages feed account)]
{:status 200
:content-type "text/html"
:body body}))
Each element of the home page logic can be verified by providing one of these functions with the right input, and verifying some properties of the output. There is no need to mock up state or simulate page interaction unless you are also using clojurescript on the front end (and even in that case the logic you want to verify can be abstracted from the interface of the browser to avoid the need for replay testing).
I am trying to write a middleware for converting all the string object ids in the request to ObjectId objects.
I am achieving this using the following:
(defn get-object-id
[id]
(when (and (string? id) (re-matches object-id-regex id))
(ObjectId. id)))
(defn maybe-obj->object-id [obj]
(or (get-object-id obj) obj))
(defn- convert-string->object-ids [obj]
(cwalk/postwalk
(partial pcommon/maybe-obj->object-id) obj))
(defn warp-params-string->objectid
"convert strings to object ids"
[handler]
(fn [request]
(handler (update-in request [:params] convert-string->object-ids))))
This is working for all the params coming for json, request params etc. But this is not applying to the route params, e.g. :fst for url "/:fst". I looked at the GET macro and the route params are being injected somewhere inside that macro. However since GET/POST etc are executed last, my middlewares do not have access to these. Any graceful way of achieving this.
Those /:foo/:bar-style parameters get bound as a result of pattern matching on URIs, with the patterns specified in the individual routes' definitions. Outer layers don't even know what the patterns look like. So, not really possible to lift processing of these to middleware.
Instead, you could write a macro, say with-preprocessed-params, to wrap your route handlers' bodies in. If it ends up being useful in many handlers, you can additionally provide your own versions of GET & Co., delegating to Compojure's macros with the body wrapped in your param-processing macro.
That's not really a good solution if you were hoping to use the results of this preprocessing in further layers of middleware. In that case, assuming you're happy to leave matching actual URI path segments to the core handler layer, you can perform your preprocessing of other parameter types in a piece of middleware, then use your GET & Co. variants to preprocess the route parameters only.
I'm developing a web application with Clojure, currently with Ring, Moustache, Sandbar and Hiccup. I have a resource named job, and a route to show a particular step in a multi-step form for a particular job defined like this (other routes omitted for simplicity):
(def web-app
(moustache/app
;; matches things like "/job/32/foo/bar"
:get [["job" id & step]
(fn [req] (web.controllers.job/show-job id step))]))
In the view my controller renders, there are links to other steps within the same job. At the moment, these urls are constructed by hand, e.g. (str "/job/" id step). I don't like that hard-coded "/job/" part of the url, because it repeats what I defined in the moustache route; if I change the route I need to change my controller, which is a tighter coupling than I care for.
I know that Rails' routing system has methods to generate urls from parameters, and I wish I had similar functionality, i.e. I wish I had a function url-for that I could call like this:
(url-for :job 32 "foo" "bar")
; => "/job/32/foo/bar"
Is there a Clojure web framework that makes this easy? If not, what are your thoughts on how this could be implemented?
Noir provides something similar. It's even called url-for.
The example function you have mentioned could be implemented as below. But I am not sure if this is exactly what you are looking for.
(defn url-for [& rest]
(reduce
#(str %1 "/" %2) "" (map #(if (keyword? %1) (name %1) (str %1)) rest)))