thereq

online coding interviews

[why?] [how?]

tech.thereq.com
the way we do the things we do

Loading page content via AJAX in Rails 3.1

It’s not uncommon to want to load part of your page content via an AJAX request. For example, on a blog post, perhaps the blog itself is returned in the HTML of the main request, but you wish to add the comments and comment form using AJAX.

There are several reasons you might want to do this:

  1. The AJAX loaded content is more expensive to calculate. If you leave it out of the main request the user will still have something to start looking at while your server churns out the remaining information.
  2. You want to cache most of the HTML of the page, and then render a personalized nugget or two via AJAX.

The Rails UJS library provides handy shorts for submitting links and forms via AJAX without having to actually write any Javascript yourself. But - there are no handy helpers for the simpler task of just loading up the contents of a particular div via AJAX.

The simplest way to do this to use the jQuery load method.

$("#comments").load("/blogs/2/comments");

The awkward part is the AJAX path (/blogs/2/comments) which clearly changes according to which blog we are viewing. If we followed the jQuery documentation exactly, we could just plop a script tag in the middle of our HTML body, so that in our template file we might have something like

# show.html.erb

<div id="comments"></div>
<script>
  $("#comments").load("<%= blog_comments_path(@blog)%>");
</script>

Yuck. Not a fan of javascript mixed into my template files.

What to do instead? Follow the pattern suggested by Rails UJS and take advantage of the new HTML data- attributes.

First, when you want to load AJAX content in your page, do the following in your template

#show.html.erb

<div id="comments" data-load="<%= blog_comments_path(@blog. :format => :js)%>">
</div>

Second, add the following to your application.js

# application.js or any JS file loaded within application.js

$("div[data-load]").filter(":visible").each(function(){

  var path = $(this).attr('data-load');
  $(this).load(path);

});

And voila! Your comments div will magically be filled by whatever is returned by the /blogs/3/comments path!

Blog comments powered by Disqus