Rails Remote Links and Buttons

rails

Rails has fantastic AJAX and unobtrusive JavaScript support. I’ve found that I can usually get 80% of the effect that one would normally build with a JavaScript framework like backbone or angular with rails remote actions for about 20% of the effort - usually a good trade, especially early in a project. Here’s a five minute rundown of how to use them.

You can add the remote: true parameter to any link_to or button_to or form_for. Behind the scenes, rails will do some magic to make that link, when clicked, fire off an XHR HTTP request to whatever action you specified. The request gets sent to the controller in your rails application just like it normally would - adding remote: true doesn’t change which parameters get sent, or how they’re formatted, just whether they are sent with AJAX or a regular, page-refreshing HTTP request.

The only difference in the controller is that instead of returning html via the format.html block, it’ll return JavaScript via the format.js block. As such, the template that will be rendered won’t be (for example) /show.html.erb, it’ll be /show.js.erb. The .js.erb file is exactly what you’d expect - JavaScript with embedded ruby. The JavaScript that gets produced gets run the page just like any other JavaScript, and you have full access to jQuery and the rest of your JavaScript libraries.

What’s the easiest way to make use of this? The easiest way is to use your .js.erb file to render a partial and replace the element on the page with your rendered partial. Let’s say you have a partial called _item.html.erb which renders an Item object. Suppose that on some page somewhere you have a ‘featured item’ display that calls <%= render "item", item: @item %>, which renders your _item.html.erb partial. You want to be able to refresh it to re-render the same item with a button.

Your featured item display might look like this:

1
2
3
<div id="featured-item">
  <%= render "item", item: @item %>
</div>

Your link will look like this (of course, you can add any styling class: and such that you like):

1
<%= link_to "Refresh", item_path(@item), remote: true %>

What should we put in show.js.erb? This will work:

1
$("#featured-item").html("<%=j render "item", item: @item %>");

This will call the .html method, which replaces the inner html of the target element with its argument. The <%=j allows us to embed the result of some ruby expression, but with appropriate escaping so that it is a valid JavaScript string. And render "item" does exactly what it always does, rendering a partial into a string of html.

That’s it. Now when you click the ‘refresh’ link, it’ll replace the content of #featured-item with the appropriate new content. Hooray, AJAX!

Of course, you can get fancier with it - you can put any (and as much) JavaScript as you want in your .js.erb files, but keeping it to a dull roar is probably ideal. The only downside of these methods is that the actions can be somewhat hard to debug, because if there is a parse error on your JavaScript generated by .js.erb, it won’t appear in your JavaScript console. To debug, you can (on Chrome / Chromium) go to the developer console, find the “Network” tab, and use the display to find the body the appropriate XHR request, then copy-paste it into the JavaScript console, where any parse errors will be displayed. Not optimal, but this is still a great technique.

Happy coding!