Building With Ajax and Rails


So, since the last time you brushed your teeth, Ruby on Rails has only grown in popularity. The list of web applications using the exciting new web framework has grown to such an enormous size, it has exceeded the 50K per page limit of the wiki used to host it. Lesser languages like Java and PHP are copying the stylish efficiency of Rails with their own frameworks like Trails, Trax and Cake.

In the tutorial Ruby on Rails for Beginners, we went over the very basic basics of Ruby and Rails:what it is, why it’s so mindblowingly cool, which celebrities are using it, and so forth. As soon as the article went live, letters flooded in, offering me book contracts, movie deals and exotic snacks — I haven’t gotten so much attention since my Ajax for Beginners article. In fact, this poll from the redoubtable says that Ruby on Rails and Ajax are among the two most popular things in the world, and plainly it pays to follow the trends, so what if we combined the two of them? No, that would be excessive. You don’t want to read about that. You do? Hmmmm, OK, I suppose we can take a quick look.


  1. You Got Ajax In My Rails
  2. Adding Prototype.js
  3. Form Of:A Form!
  4. Moving Onward


You Got Ajax In My Rails

Let me just refresh my memory a little. Ajax (it seems like everyone’s calling it that now rather than my spiffy coinage, “XHR”) is the handy JavaScript technique that allows the browser to communicate with the server without reloading the current page, to do things like validate or save form input, refresh images and heaven knows what else.

In the Ajax for Beginners article, we created those client-side dynamic functions by typing in a bunch of code by hand, but that goes against the make-it-quick-and-easy methodology of Rails. Instead, there are some pleasurably easy, automated ways to incorporate Ajax into a Rails-driven site. Rails ships with thePrototype JavaScript library, which provides a nice high-level toolkit for working with Ajax functions, and with, which builds additional bells and whistles onto Prototype. These two can be downloaded separately and used in non-Rails projects as well.


Adding Prototype.js

Let’s revisit the example site from the Ruby on Rails for Beginners article. Maybe you’ve still got a copy of it lying around on your web server, or maybe you’d like to create it again from scratch. I’ll wait here.

You’ll notice that the public/javascripts directory contains a file called “prototype.js” — that’s our friend Prototype! There isn’t much documentation for it, but if you read JavaScript fluently you can look at the file and see the basic methods it defines. In order to use the methods, first and foremost we need to activate them. That can be done one Ruby block at a time or for a whole page; let’s choose the latter. In the rHTML file that contains the page layout, namely app/views/layouts/bookmarks.rhtml, insert the line

1 <%= javascript_include_tag :defaults %>

right before the closing  /head¢ tag.

Then we can get right down to creating our Ajax snazz. In our last session, we looked at HTTP links that used the Ruby function link_to(). Remember that? They looked like this (an example fromapp/views/bookmarks/list.rhtml):

1 <%= link_to 'Destroy', {:action => 'destroy', :id => bookmark}, :confirm =>"Are you sure?" %>

Well, link_to() has a buddy called link_to_remote(). It works in a similar fashion, except it takes an additional parameter, besides the name of the link and the action or URL it points to:a DOM element ID. The Ajax action will place any content it retrieves from the server into that element. So, if we wanted to rewrite our function above, so we could delete a bookmark from our list without reloading the whole page, we’d say:

1 <%= link_to_remote 'Destroy', {:action => 'ajaxdestroy', :id => list, :update => 'bookmarks'}, :confirm => "Are you sure?" %>

Notice the :update parameter – that’s the one that’s new. Now, when we click the Destroy link, it calls theajaxdestroy action to delete the bookmark in question from the database, but instead of a page reload in the browser, the server will do the work behind the scenes and just return a new bookmark listing, which will be placed in the list DOM object. That DOM object corresponds to the list of bookmarks on the page. Now, that xhrdestroy action doesn’t exist yet. We have to create it, inapp/controllers/bookmarks_controller.rb:

01 def ajaxdestroy
05  Bookmark.find(@params[:id]).destroy
09  render :partial => "bookmarks"
13 end

The first line does the deleting:it looks at the @params array sent by the browser, which contains the ID of the bookmark to be deleted; finds the corresponding row in the database; and destroys it. Simple enough, I hope. The second line returns the response, using the very handy render() method. This method can be used to create and send a “partial,” or chunk of a web page, which it does here:the rendered list of bookmarks is returned and displayed without a full reload. It’d be wise to include fallback options for browsers that don’t support Ajax, but I leave that to you, my intelligent reader.


Form Of:A Form!

In our Ajax for Beginners lesson, we wrote a PHP/JavaScript function that would automatically grade essays and return the numeric grade in an alert window. To do the same with Rails, we’d use a method called form_remote_tag(), which submits a form to a server-side handler via XMLHTTPRequest. This is an Ajax version of the more familiar form_tag().

01 <%= form_remote_tag(:url => {:action => 'grade'}, :update
05 => result) %>
09        Enter your essay here:
13        <%= text_area_tag "essay" %>
17        <%= submit_tag "What's my grade?" %>
21        Result:
25        <%= text_field_tag "result" %>
29      <%= end_form_tag %>

The user types their little essay into the text area created by text_area_tag. The form content is submitted to the controller action “grade,” which we will define in a minute. That action grades the essay and sends a numeric grade back to the form, which displays it in the “result” text field — all without reloading the page. (I know, it’s less and less thrilling every time I say that. Still a little cool though, right?) The grading action, which lives in the app/controllers directory, looks like this. Feel free to substitute your own more-rigorous, essay-grading algorithm:

1 def grade
5  puts params[:essay].strip.squeeze.split(/s/).size
9 end

OK, that “grading” function really just does a word count, using Ruby’s redoubtable string methods. I’ve used it to grade my students’ papers though and it seems to work just fine.

puts is the Ruby equivalent of echo or print. Ruby, unlike some languages you may know, doesn’t need values to be explicitly returned from its methods. Instead, the final output of the method is automatically returned to the method’s caller. params is the array containing the entire submitted form, params[:essay]is the essay, strip removes leading and trailing white space, squeeze removes multiple repeating characters so double spaces aren’t counted twice, split breaks the string at every remaining space into an array, and size returns the number of elements in that array, i.e. the word count.


Moving Onward

Those two methods give you plenty to work with, Ajax-on-Rails-wise (“Rajax”? Would that catch on, you think?) There are a dozen or so more, though, documented here. observe_field and observe_formcreate event handlers that make Ajax calls when a field changes. Very handy for autocompletion.draggable_element makes a DOM object draggable. It can then be dropped on an element specified withdrop_receiving_element. For flashier stuff, you can check out some of the demos at

Now that it’s so easy to create snazzy Ajaxy database-driven websites, the next step is for some of you to go out there and actually make good ones. I look forward to clicking your buttons and dragging your elements!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>