AJAX on Rails 2.1



Ajax stands for Asynchronous JavaScript and XML. Ajax is not a single technology; it is a suite of several technologies. Ajax incorporates the following −

  • XHTML for the markup of web pages
  • CSS for the styling
  • Dynamic display and interaction using the DOM
  • Data manipulation and interchange using XML
  • Data retrieval using XMLHttpRequest
  • JavaScript as the glue that meshes all this together

Ajax enables you to retrieve data for a web page without having to refresh the contents of the entire page. In the basic web architecture, the user clicks a link or submits a form. The form is submitted to the server, which then sends back a response. The response is then displayed for the user on a new page.

When you interact with an Ajax-powered web page, it loads an Ajax engine in the background. The engine is written in JavaScript and its responsibility is to both communicate with the web server and display the results to the user. When you submit data using an Ajax-powered form, the server returns an HTML fragment that contains the server's response and displays only the data that is new or changed as opposed to refreshing the entire page.

For a complete detail on AJAX you can go through our AJAX Tutorial.

How Rails Implements Ajax

Rails has a simple, consistent model for how it implements Ajax operations. Once the browser has rendered and displayed the initial web page, different user actions cause it to display a new web page (like any traditional web application) or trigger an Ajax operation −

  • Some trigger fires − This trigger could be the user clicking on a button or link, the user making changes to the data on a form or in a field, or just a periodic trigger (based on a timer).

  • The web client calls the server − A JavaScript method, XMLHttpRequest, sends data associated with the trigger to an action handler on the server. The data might be the ID of a checkbox, the text in an entry field, or a whole form

  • The server does processing − The server-side action handler (Rails controller action), does something with the data and returns an HTML fragment to the web client.

  • The client receives the response − The client-side JavaScript, which Rails creates automatically, receives the HTML fragment and uses it to update a specified part of the current page's HTML, often the content of a <div> tag.

These steps are the simplest way to use Ajax in a Rails application, but with a little extra work, you can have the server return any kind of data in response to an Ajax request, and you can create custom JavaScript in the browser to perform more involved interactions.

AJAX Example

While discussing rest of the Rails concepts, we have taken an example of Library. There we have a table called subject and we had added few subjects at the time of Migration. Till now we have not provided any procedure to add and delete subjects in this table.

In this example, we will provide, list, show and create operations on subject table. If you don't have any understanding on Library Info System explained in the previous chapters, then we would suggest you to complete the previous chapters first and then continue with AJAX on Rails.

Creating Controller

Let’s create a controller for subject. It will be done as follows −

C:\ruby\library> ruby script/generate controller Subject

This command creates a controller file app/controllers/subject_controller.rb. Open this file in any text editor and modify it to have the following content −

class SubjectController < ApplicationController
   layout 'standard'
   def list
   end
   def show
   end
   def create
   end
end

Now, we will discuss the implementation part of all these functions in the same way we had given in the previous chapters.

The list Method Implementation

def list
   @subjects = Subject.find(:all)
end

This is similar to the example explained earlier and will be used to list down all the subjects available in our database.

The show Method Implementation

def show
   @subject = Subject.find(params[:id])
end

This is also similar to the example explained earlier and will be used to display a particular subject corresponding to the passed ID.

The create Method Implementation

def create
   @subject = Subject.new(params[:subject])
      
   if @subject.save
      render :partial => 'subject', :object => @subject
   end
end

This part is a bit new. Here we are not redirecting the page to any other page; we are just rendering the changed part instead of whole page.

It happens only when using partial. We don't write the complete view file, instead, we will write a partial in the /app/view/subject directory. We will see it in a moment. First, let's create view files for other methods.

Creating Views

Now we will create view files for all the methods except for create method for which we will create a partial.

Creating View for list Method

Create a file list.rhtml in /app/view/subject and populate it with the following code.

<h1>Listing Subjects</h1>
<ul id="subject_list">
   <% @subjects.each do |c| %>
   <li><%= link_to c.name, :action => 'show', :id => c.id %>
   <%= "(#{c.books.count})" -%></li>
   <% end %>
</ul>

Here, you are iterating through the @subjects array and outputting a <li> element containing a link to the subject it is referencing for each item in the array. Additionally, you are outputting the number of books in that specific subject inside parentheses. Rails' associations make it easy to step through a relationship and get information like this.

Now, try browsing your Subject list using http://localhost:3000/subject/list. It will show you the following screen.

List Subjects

Creating View for show Method

Create a file show.rhtml in /app/view/subject and populate it with the following code.

<h1><%= @subject.name -%></h1>
<ul>
   <% @subject.books.each do |c| %>
   <%= link_to c.title, :controller => 
      "book", :action => "show",:id => c.id -%>
   <% end %>
</ul>

Now, try clicking on any subject and you will find a listing of all the books available under that subject.

Creating View for create Method

We would not create view for the create method because we are using partial instead of view. In the next section, we will create a partial for the create method.

Adding Ajax Support

To get Ajax support in the Rails application, you need to include the necessary JavaScript files in the layout. Rails is bundled with several libraries that make using Ajax very easy. Two libraries - prototype and script.aculo.us are very popular.

To add Prototype and script.aculo.us support to the application, open up the standard.rhtml layout file in app/views/layouts, add the following line just before the </head> tag, and save your changes −

<%= javascript_include_tag :defaults %>

This includes both the Prototype and script.aculo.us libraries in the template, so their effects will be accessible from any of the views.

Now, add the following code at the bottom of app/views/subject/list.rhtml.

<p id="add_link"><%= link_to_function("Add a Subject",
   "Element.remove('add_link'); Element.show('add_subject')")%></p>
<div id="add_subject" style="display:none;">
   <% form_remote_tag(:url => {:action => 'create'},
      :update => "subject_list", :position => :bottom,
      :html => {:id => 'subject_form'}) do %>
      Name: <%= text_field "subject", "name" %>
   <%= submit_tag 'Add' %>
   <% end %>
</div>

We are using link_to_function instead of link_to method because the link_to_function method enables you to harness the power of the Prototype JavaScript library to do some neat DOM manipulations.

The second section is the creation of the add_subject <div>. Notice that you set its visibility to be hidden by default using the CSS display property. The preceding link_to_function is what will change this property and show the <div> to the user to take input required to add a new subject.

Next, you are creating the Ajax form using the form_remote_tag. This Rails helper is similar to the start_form_tag tag, but it is used here to let the Rails framework know that it needs to trigger an Ajax action for this method. The form_remote_tag takes the :action parameter just like start_form_tag.

You also have two additional parameters − :update and :position.

  • The :update parameter tells Rails' Ajax engine which element to update based on its id. In this case, it's the <ul> tag.

  • The :position parameter tells the engine where to place the newly added object in the DOM. You can set it to be at the bottom of the unordered list (:bottom) or at the top (:top).

Next, you create the standard form fields and submit buttons as before and then wrap things up with an end_form_tag to close the <form> tag. Make sure that things are semantically correct and valid XHTML.

Creating Partial for create Method

We are calling the create method while adding a subject, and inside this create method, we are using one partial. Let’s implement this partial before going for actual practical.

Under app/views/subject, create a new file called _subject.rhtml. Notice that all the partials are named with an underscore (_) at the beginning.

Add the following code into this file −

<li id="subject_<%= subject.id %>">
   <%= link_to subject.name, :action => 'show', :id => subject.id %>
   <%= "(#{subject.books.count})" -%>
</li>

You are done now and can easily add several subjects without having to wait for the page to refresh after each subject is added. Now, try browsing your Subject list using http://localhost:3000/subject/list. It will show you the following screen. Try to add some subject.

Add Subject

When you press the Add button, subject would be added at the bottom of all the available subjects and you would not have a feel of page refresh.

Advertisements