How to solve the problem of Javascript-rich interfaces with a Rails backend.
RJS is dead
Do you remember RJS? It was introduced somewhere around version 1 of rails (or even earlier, please correct me) and provided a template language in pure ruby to respond to AJAX actions.
1 2 |
|
This was still during the benign reign of Prototype
and the template would have been called update.rjs
. There also was a way of
rendering Javascript directly from your controller actions:
1 2 3 4 5 6 7 8 9 10 |
|
The significant part here is the page
object, which magically generated
Prototype-JS for us. But over time, RJS became deprecated. I did not follow
the proceedings, so I do not know the reasons. Maybe it tempted to pinch the MVC
layer a little bit too much (Controller example above) or with the rise of
jQuery (yeah!) it lost its primer target. Or there was to
much magic involved.
I admit, if not properly cleaning up after every commit, RJS templates could
become a mess. Additionally, the interaction with helpers was strange. You
could call a helper on the page
object, but from within this helper, the page
object was only accessible through hoops. So no real refactoring was possible.
Until now!
Long live RJS!
I think the current approach of generating JS from Rails is tedious.
lala.js.coffee.erb
looks nice in theory, but in practice this is a mess. My
HAML-coddled eyes don’t want to see no angle brackets no more! Manual escaping of HTML?
Letting Rails serve only JSON on the other hand makes a full-blown Rails stack kind of
obsolete.
With the recent occurrence of Presenters like Draper or your own quickly setup presenter, it now becomes possible to write Rails applications controller their browsed views by Javascript. I will show my findings with the first, but it may easily achieved with every other class following decorator pattern (TM).
Add draper and versatile-rjs to your Gemfile to resurrect that magic zombie.
1 2 |
|
Open a bottle of champagne, dim the light, and initialize first contact.
Put this into an initializer or your favored monkey patch cage and require it once during application startup.
And it may prevail
As demonstrated in the comment of above gist, you can still know extend the
page
proxy, but use the presenter around it. And because it uses jQuery (of
course), the calls to it can be chained. In our code we use symbol-based
lookup for elements on the page. Here is some example code; some endpoints are
still missing, but you’ll get the idea.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
So…
There we go, finally a JS generating interface that looks clean, removes duplication and uses all the Rails’ features.