More readable Compojure routes

I am working on a small Ring / Compojure webapp and I am wondering if there is a way to resolve routes. I am using the standard Clojure destructuring, but you need quite a few of the arguments passed to this function.

This is fine, using Compojure-specific destructuring:

(POST "/login/" [email password] (login-post email password)) ; handle login attempt

      

Now it starts to deteriorate. I need to provide a function to both flash message and email stored in the session:

(GET "/login/" {flash :flash {email :email} :session} (login-get flash email))

      

And here is the route for submitting data through the form:

(POST "/" {{user-email :user-email} :session {title :title} :params {tags :tags} :params { content :content } :params { privacy :privacy } :params} (home-post user-email title tags content privacy))

      

I know I can just send a raw request to the home-post function using: params, but I somehow feel like placing the parameter highlight using routes is the best solution. This makes home mail cleaner and easier to test. Introduce only rendering each feature of the giant request map.

Could deconstructing in defining routes be clearer (more readable), fx, using some sort of map extraction function, macro, anything?

Pro and con to accommodate destructuring with routes?

+3


source to share


1 answer


First of all, I agree with your assessment that the destructuring of the request usually belongs to the definitions of the route handler. The very fact that Compojure provides an extension to Clojure's destructuring syntax indicates that the author also felt the same way.

There are several things you can do to reduce duplication in your destructuring forms. First off, Clojure's standard map binding will help with the last route you posted. The first thing you can do is combine the keys that you retrieve from the request :params

:

(POST "/" {{title :title, tags :tags, content :content, privacy :privacy} :params ...} ...)

      

This is a bit clearer, but since you are not renaming any of the values ​​you pull from :params

, you can do better:

(POST "/" {{:keys [title tags content privacy]} :params ...} ...)

      

This is about how much Clojure's destructuring syntax will help you, but you can even use Compojure's additional compositing syntax for DRY even more. Compojure assumes that you will most often be interested in getting values ​​from a :params

query key , so you can use vector destructuring to pull them out:



(POST "/" [title tags content privacy] ...)

      

Much better. Since you still need to get additional values ​​from the request, you can specify :as the-request

at the end of the binding vector to directly access the request:

(POST "/" [title tags content privacy :as req] ...)

      

Be aware, however, that this variable can also be destroyed. With all that in mind, here's a simplified version of your last route:

(POST "/" [title tags content privacy :as {{user-email :user-email} :session}]
  (home-post user-email title tags content privacy))

      

I hope this is helpful! The more Clojure you write, the more ways you can make your code easier to understand and understand.

+4


source







All Articles