In what way?
In what way?
Here's my list:
- Database migrations
- Fast TDD (for some sub-Gary Bernhardt definition of fast) with access to the app environment.
- content negotiation
- Authentication with Devise and Omniauth
- Easy built-in support for caching
- Easy built-in support for background queue systems
- Easy support for one-off or occasional scripts with access to the whole app environment (rake tasks)
- Pry (yes, Clojure has awesome REPL powers, but Pry is so easy to use, and you have access to the whole app environment (no loading / switching namespaces or abuse of user.clj))
There's probably some solution to each of these. But all require you to find/know the options, and be able to evaluate which is best for you ("all REAL devs . . ." sure, sure). For Rails, all of these are available to you in the Rails Guides, except for Devise+Omniauth, which has an extensive wiki and tons of StackOverflow answers.
Out of interest, what makes Pry easier to use? I'm not sure I understand the comment about having access to the whole app environment. In the Clojure REPL you do as well...?
The app environment thing is mostly about having to switch between a lot of namespaces and/or to make sure they're all loaded upon starting the REPL. With Rails+Pry, you can work with any class in your app immediately. It also lets you put breakpoints in your code, where executing the code in a running process throws you into a REPL at that point, with all the local context up to that point of execution. Also, if you make code changes, you simply type "reload!" in the REPL and everything's up to date. I have a bookmark to read Stuart Sierra's post about his workflow to try to get a grip on how to come close to something like that in Clojure.
And it can do a lot more great stuff, too: https://www.youtube.com/watch?v=4hfMUP5iTq8
Oh and by the way -- thanks for all of your OSS work in the Clojure world! Especially taking the extra step of providing good docs.
There are also a few projects for adding in debug REPLs, but those seem to have fallen by the wayside lately, perhaps supplanted by debuggers.
You might also want to talk a look at Duct (https://github.com/weavejester/duct), which is my ongoing and still early attempt at solving some of the framework problems with Clojure. If you create a template via Duct, like so:
lein new duct foobar +site +cljs
Then you some of the things you're asking for. The namespaces of your application are loaded when you start `lein repl`. You get a `(reset)` function that reloads your code, restarts your application and pushes those changes dynamically to the browser. You also get a ClojureScript REPL that hooks into the browser.There are also generators, migrations, database support etc., but currently all inferior to Rails. I'm probably going to be working on the generators next, as they need attention.
TLDR; Yes, clojure is behind in regards of web development, but it is not as bad as you said. There is active work done in this area.
I totally agree with what you said. It is a general understanding in the clojure community that you compose libraries to get things done. However, for web development that still means a lot of repitition, thats why I created the closp template.
It is based on luminus (http://www.luminusweb.net/) which is a lighter "framework" with more options.
My idea was to provide one way with sensible defaults to get started in doing web stuff in clojure.
I still work regularly on it and would be happy about contributions / feature requests. Whereas regularly means in terms of months as I do this all in my spare time.
Also I am quite active in the clojure community and I know that luminus is not shunned, but instead it also receives improvements and releases regularly. Also the author of luminus works professionally with clojure and with luminus.
And I have to admit, that luminus has the far superior documentation, he has done a good job on it I think.
I think the fact that these things aren't magically is a big plus. You can use the defaults, but you can trivially customize the middleware stack for your specific needs.
Another thing to note is that a lot of the stuff that traditional frameworks do is geared towards doing presentation on the server. Modern apps tend to do presentation on the client, and the server primarily provides a set of stateless services for the client to fetch the data that it needs. With this approach, you don't really need a complex server framework in the first place.
(defn login [{{:keys [email password]} :params session :session}] ...)
Also remember as well as the :keys special form you have :strs and :syms.