Skip to main content

An Introduction to using AJAX with Rails

Posted by bleonard on July 6, 2007 at 11:16 AM PDT

The Rails framework comes bundled with the Prototype and Scriptaculous Javascript libraries. In this entry I'll introduce how to use those libraries in a Rails application.

Setting Things Up

I'm going to begin from where I left off in my previous post: Rails and Model Relationships. Alternatively, you can start from BlogDemoComments.zip, which is the completed project from that post.

Test the BlogDemo Project

  1. Open the BlogDemo project.
  2. Note, if you are starting with the provided BlogDemo project, you will also need to create the BlogDemo_development database and run the migrations.
  3. Run the project and browse to http://localhost:3000/blog to verify that it works.

The Plan

Currently, when a new comment is added, the entire page - blog entry and comments - are reloaded. Instead, we'll use AJAX to only reload the comments. Just for fun, we will also show how to apply a visual effect to highlight the most recently added comment.

Preparation

First we're going to move the fragment of rhtml that we want to dynamically reload into a partial template.

  1. Ctrl+N to create a new RHTML file. Name the file _comments and place it in the app\views\blog folder.
  2. Alt+Shift+O to open show.rhtml.
  3. Cut the following block of code from show.rhtml:







    And paste it into _comments.rhtml, replacing all existing content in _comments.rhtml.


  4. Return to show.rhtml and insert the following call to the partial from where you cut the code. Note, the
    will be used later to reference this chuck of code when we dynamically reload the comments:



    <div id="comments">
        <%= render(:partial => "comments", :object => @post_comments) %>
    div>
  5. Test your changes. The application should behave as it did before.

Change the POST to an XMLHTTPRequest

  1. First, let's make sure the JavaScript libraries we're going to use are included in our application. Alt+Shift+O to open blog.rhtml and add the following line below the stylesheet_link_tag:



    <%= javascript_include_tag :defaults  %>
    We're passing :defaults as the source because we're going to be using the Prototype and Scriptaculous libraries that come bundled with Rails.


  2. In show.rhtml, change the form_tag, which performs a HTTP POST, to a form_remote_tag, which performs an XMLHTTPRequest, as follows:



    <% form_remote_tag :url => {:action => "post_comment"} do %>

  3. Test. The entire show page is still reloaded on submit. This is because the post_comment action in blog_controller forces the reload by calling the show action.






  4. Comment out the redirect_to call in the post_comment action and try again. Things are getting worse, as now we get a Template is missing error:







    This is actually progress, as now we can insert an RJS (Ruby JavaScript) template to handle the XMLHTTPRequest.


  5. Right-click the Views -> blog folder and select New -> Empty RJS Template. Name the template post_comment.


  6. Now we'll use the page object to replace the html at the
    we labeled "comments" above:



    page.replace_html "comments", :partial => "comments", :object => @post_comments
  7. Test again:







    As the message indicates, the problem is with line 4 above -- @post_comments is nil. If we look back into the blog_controller, @post_comments was being set in the show action, which we are no longer calling.


  8. Add the following three lines after the redirect we commented out earlier in post_comment action:



          #redirect_to :action => 'show', :id => flash[:post_id]
          @post = Post.find(flash[:post_id])
          @post_comments = @post.comments.collect   
          flash[:post_id] = @post.id  #Store the post.id back in the flash
  9. Test one final time and our comments should now be dynamically updated.

Apply Visual Effects

The Scriptaculous library comes with a bunch of visual effects. I'm going to apply the highlight effect to the comment just posted. Once in place, you can easily swap in and try out any of the other effects.

  1. Like we did above for the entire comments section, we need to label the comment to which we want to apply the visual effect. We'll do this by adding a div to the most recently added comment. Open _comments.rhtml and replace the
  2. line with the following:



        <% if @post_comments.index(comment) == @post_comments.length-1 %> 
           
            <li id="new_comment"><%=h comment.comment %><br>
        <% else%>
            <li><%=h comment.comment %><br>
        <% end %>
  3. Then switch to post_comment.rjs and add the following:



    page[:new_comment].visual_effect :highlight
  4. Test the end result:







    The highlight will appear for just a second and then fade away.

 

The Completed Application

BlogDemoAJAX.zip

Related Topics >>