Javascript + embedded Ruby templates with Rails, out-of-the-box
I recently tried using Dan Webb’s MinusMOR plugin, which allows you to write Javascript templates with embedded Ruby (a la .html.erb/.rhtml templates), but I was disappointed to find out it didn’t work with Edge Rails.
I found a random Pastie via Google that seemed to fix the plugin for Edge, and this worked okay, with the caveat that you couldn’t render partials that used the new .html.erb naming scheme (just .erb would work), and given this, and the fact that MinusMOR’s author wasn’t keeping this plugin up-to-date, I was hoping to find a better solution.
And I did find a better solution — if you’re using Edge Rails, you can create Javascript templates with embedded Ruby out-of-the-box, no plugins or monkeypatching necessary. You just need to name the template in the action.js.erb format. Example:
Controller:
def create
…
# if you’re only returning Javascript from this action,
# you can omit the respond_to block
respond_to do |format|
format.js
end
end
View:
alert("created");
.. and the Javascript is rendered, sans layout, with a “text/javascript” Content-Type. All good so far.
JSON-escaping with “js” helper
Next thing we need is, a helper so that we can do JSON-compliant escaping (which RJS does automatically) — I took this helper straight from the MinusMOR plugin, and put it in my application helper:
def js(data)
if data.respond_to? :to_json
data.to_json
else
data.inspect.to_json
end
end
Usage example:
alert(<%= js "url is /posts/5" %>);
Renders:
(Textmate users: I’m using the HTML (Rails) filetype for my js.erb files, which, while it doesn’t do any Javascript syntax highlighting, it does highlight inline Ruby syntax, and it allows me to use the ctrl-shift-> shortcut to create <%= %> blocks.)
Rendering partials with “partial” helper
MinusMOR has a ‘partial’ helper — we can use that, too — I’ve adapted it so that partials with the new .html.erb syntax can be recognized:
# enhanced with ability to detect partials with template format, i.e.: _post.html.erb
def partial(name, options={})
old_format = self.template_format
self.template_format = :html
js render({ :partial => name }.merge(options))
ensure
self.template_format = old_format
end
Usage example (syntax is jQuery):
$("#posts").append(<%= partial ‘post’,
Renders:
So, just add these two helpers to your application helper, and you should be good to go.
jQuery “selector” helper
One last helper, for jQuery users — a selector helper for creating id selectors from an object:
js "##{dom_id(obj)}"
end
Usage example:
$(<%= selector @post %>).highlightFade();
Renders:
10 Comments