I have a couple of suggestions.<p>1. If you return a handler function from a Compojure route, the handler is evaluated with the request. So:<p><pre><code> (GET "/" request (posts/all request))
</code></pre>
Is the same as:<p><pre><code> (GET "/" [] posts/all)
</code></pre>
So there's no need for a separate "route" macro.<p>However, passing the full request map is discouraged, because the more information you give a function, the more things can theoretically affect it. Functions should be limited in what they know and what they can do, and this is one of the principles Compojure is designed around.<p>2. Some of the macros you've written for Korma could be written as functions instead. For example:<p><pre><code> (defn paginate [query page per-page]
(-> query (limit per-page) (offset (dec page))))
(post/all (where conditions) (paginate page per-page))</code></pre>
This is a pretty interesting post, but I'm seeing a common thread in most "experience reports" regarding making a webapp in Clojure.<p>They're all built with with the presumption that the person doing the frontend work (HTML, CSS, JS) will also be doing the backend (Clojure, database) coding.<p>This is almost never the case in my line of work.<p>Hiccup violates this principle by embedding the html <i>in my Clojure</i> and Enlive couples markup with data tightly in ways that horrify me.<p>The only approach I've seen that could work for more serious projects is using stencil because then the map of data you pass to the template-side is a 'contract' of sorts, but they can work with the data you pass however it works for them.<p>That's somewhat regrettable as I prefer Jinja-style templating to mustache, but Stencil (mustache) is the only viable alternative I've found.<p>I cannot possibly be the only person with a keen interest in Clojure who hasn't abandoned division of labor.
I have used Enlive and I still prefer traditional erb style templates. I actually use Slim(slim > haml) or Haml, but they are just syntactic sugar.<p>Enlive, on one hand, allows designers to work on html which doesn't need any data binding, and then process the plain html. On the other hand, it's tightly coupled with the markup. A designer can't be sure that changing a class name or restructuring the markup won't break the templates.<p>Rolling your own validations might be fun, or it isn't something I want to do when I am working on a project. I might have rolled out validations from last project which I can re-use, but I still prefer AR or WTForm validation over rolling my own(takes time, and if I am in a hurry, ends up not being generic enough to use in another project). Same goes for pagination. Need pagination? Here,<p><pre><code> # Add kaminari https://github.com/amatsuda/kaminari
class UsersController
def index
@users = User.order(:name).page params[:page]
end
end
# index.html.slim
= paginate @users
</code></pre>
Done.<p>Clojure is a pleasant, expressive and innovative language, but as the blog post pointed out, the ecosystem isn't vibrant enough yet.