Rails 3, jQuery & UJS

The days of old JavaScript where writing events and handlers inline on the html DOM elements have finally passed. Rails 3 has caught up with this movement and no longer will there be source code filled with extremely verbose onclick handlers. Hopefully, if you are reading this, then you are long past this dark age method too, or maybe you just are looking to find out how Rails 3 handles the unobtrusive JavaScript (UJS) now. Either way, it took me a while to put together exactly what goes on, so I figured I would write it down.

Utilizing jQuery

I have dabbled in almost all the major players in the JavaScript library list. Starting out in MooTools and writing my first plugins, moving to Prototype — it was bundled with Rails so I figured why not, and porting over those plugins then finally landing on jQuery, of course porting over those plugins.

There are a few reasons I switched over to jQuery, and no I was not drinking the Kool-aid of joining the boat of the bigger players.

  • The syntax made sense and was so much easier to write.
  • It was faster at its traversing of the DOM compared to other libraries. I didn’t even try to use YUI, while it’s very hefty in what it does, it is extremely slow and seems to reek of code bloat.
  • It’s continuously developed on as the community seems a lot stronger than that of Prototype’s.

Rails 3 gets jQuery-fied

For a while now, Rails has always been bundled with Prototype and Scriptaculous. Now, with the awesome rails generators, you can tell it to skip that:

1
rails new test-project -J # the -J skips Prototype builder

Now that Prototype isn’t in the project, you still need the jQuery drivers to interact with the UJS. To do so, it’s as easy as installing a gem from the jquery-ujs repo on github.

1
$ > gem 'jquery-rails', '>= 0.2.6'
2
$ > rails generate jquery:install # --ui if you want jQuery UI

You can find more about what this does, but in short, it creates a rails.js file, and all the latest jQuery library files, in your javascripts directory for you to include. This file includes all the drivers for the UJS methods that Rails utilizes. Now you can write your own custom JS (or not) to interact with the callbacks the AJAX methods create.

The new Rails way

As mentioned above, Rails used to include all JavaScript calls, methods and callbacks inline in the DOM. This was a big no-no as it bloated the source code, loaded as the page rendered and was hard to customize. Now Rails leaves all the JavaScript to you.

The following are examples for creating objects in the database. Of course, these can be written to handle anything, but these are the bare examples that are typically used with UJS.

The new, but old view helpers

Gone are the old helpers:

1
remote_form_for
2
link_to_remote

And replaced by normal helpers with a few extra HTML5 type parameters:

Remote forms

1
form_for(@foo, :remote => true)

The “remote” paramter makes it a UJS form.

1
link_to(“My delete link”, “/delete/me“, data-method” => “delete”, “data-confirm” => “Are you sure?”)

The “data-“ params make it a UJS link.

So simple. These new parameters allow the rails.js file you included to recognize that there are remote forms or links on the page and handle accordingly.

The controller

No more RJS or old faux Prototype helpers. Now instead all you need to do in the controller is include the respond method to handle the xhr request.

1
def create
2
  @foo = Bar.new(params[:zook])
3
  respond_to do |format|
4
    if @foo.save
5
      format.js {} # this handles the xhr request
6
      format.html # for rendering regular html
7
    end
8
  end
9
end

The line for format.js handles the xhr request telling the app to render the view “create.js.erb.” So if you don’t already have the that file, create it now as the next step is to write some custom JavaScript.

The JavaScript

This is where the magic and customization comes in with the new Rails 3 UJS setup. Here you can write any custom Javascript to handle the callback methods with what the server returns.

Handling the callto

The rails.js file only contains the ability to perform on what to do when you throw AJAX methods to it such as the standard beforeSend, success, complete, or error. This way you can write any custom functions to interact with these callbacks. Here is a base structure of how to handle just that:

1
$(“#my_remote_form”)
2
  .bind("ajax:beforeSend", function(){
3
    // Things to do before sending
4
  })
5
  .bind(“ajax:complete”, function(){
6
    // Things to do after the ajax is sent
7
  })
8
  .bind(“ajax:success”, function(){
9
    // Things to do when it’s a successful call
10
  })
11
  .bind("ajax:beforeSend", function(){
12
    // Things to do for an error
13
  });

The beforeSend action is great for letting the user know that something is happening. This can be done by changing the value of the submit button or adding a nice AJAX spinner graphic.

Handling the server callback

So the object was successfully saved to the database, now let’s take the data returned and append it to the DOM with an animation signifier.

1
$(“#foo_list”).prepend(“<%=escape_javascript(render :partial=>’foo/bar_item’) %>");
2
$(“#foo_list”).effect(“bounce”, { times:3 }, 300);

That’s it!

So much simpler

I think the great thing about this new method is that there is no longer a reliance on knowing the RJS syntax. If you are already strong in writing jQuery syntax or just starting out, then this will become second nature. Removing the massive code from the DOM and extruding it into their own files makes debugging quicker and reduces complexity. This is just plain awesome, but that’s just my two cents.

Filed under: Code