Ajax Spy in Rails

I was playing around with Digg this morning and noticed Digg Spy. At first I thought it was really cool and wondered how they did that. Then I realized it’s just a bit of Ajax and, as anyone who’s read Pragmatic Ajax knows, Ajax is easy! So read on for how I implemented an Ajax spy in Rails and to download the code.

The first thing I did was generate a controller and model using Rich White’s excellent AjaxScaffold Generator, called EntriesController and Entry, respectively. This gave me a nice way to create new entries easily. After that I added some basic login/signup support so that the entries could be associated with users. So far, nothing out of the ordinary.

Next I created a new controller called SpyController, this is where all of the action happens. I added a basic list method which just returns all of the entries in the DB (sorry, no pagination), this is what we initially call when displaying the page. Then I added an update method which will be called periodically to retrieve new entries, it looks like this:

  1. def update
  2.   last_update = Time.parse(params[:timestamp])
  3.   # locate all of the entries created since the last update
  4.   @entries = Entry.find(:all, :order => ‘created_at ASC’, :conditions => [ ‘created_at > ?’, last_update.to_s(:db) ]);
  5.   if !@entries.empty?
  6.     render :update do |page|
  7.       for entry in @entries
  8.         page.insert_html(:top, ’spy-list’, :partial => ‘entry’, :object => entry)
  9.         page.visual_effect :highlight, "spy-item-#{entry.id}"
  10.       end
  11.     end
  12.   end
  13. end

At this point I needed some JavaScript to call the update method, so put the following code in application.js:

  1. var updateInterval = 5000; // update every 5 seconds
  2. var timestamp = new Date().toUTCString();
  3. var timer;
  4.  
  5. function go() {
  6.   timer = setInterval(‘update()’, updateInterval);
  7. }
  8.  
  9. function update() {
  10.   url = "/spy/update";
  11.   new Ajax.Request(url, {
  12.                asynchronous: true,
  13.                method: "get",
  14.                parameters: "timestamp=" + timestamp,
  15.                onSuccess: function(request) {
  16.                  timestamp = new Date().toUTCString();
  17.                }
  18.   });
  19. }

The JavaScript update method calls the SpyController’s update method and passes a timestamp as a parameter (this is the time when the page was loaded, initially, and later the timestamp is updated as new entries are retrieved). To bring it all together I had to add on onload to the list.rhtml view for the SpyController, like this:

  1. <body onload="go()">
  2. <p>This page updates automatically!</p>
  3. <br/>
  4.  
  5. <div id="spy-list" class="spy-list">
  6.   <% if !@entries.empty? %>
  7.     <%= render :partial => ‘entry’, :collection => @entries, :locals => { :hidden => false } %>
  8.   <% end %>
  9. </div>
  10. </body>

That’s all there is to it. See, I told you it’s easy! You can download the code from here (Updated for Rails 1.2.3).

3 Comments so far »

  1. Ben said,

    Wrote on March 22, 2007 @ 12:19 pm

    Thanks for the guide Sean, it is exactly what I was looking for. This will really help me to code up a “Digg Spy” type feature for my own Rails app (http://www.trawlr.com).

  2. john said,

    Wrote on April 30, 2007 @ 9:41 pm

    Heya,

    Do you have an updated link to the code? I tried to find a contact on your site so I could email you, but no luck.

    Thank you
    - John

  3. Sean Mountcastle » Implementation of Digg Spy in Rails said,

    Wrote on May 1, 2007 @ 10:17 pm

    [...] Based on a comment from an alert reader, I found out that the link was broken in my Ajax Spy in Rails post. Since I couldn’t locate the original zip file on my powerbook, I rewrote it from scratch using Rails 1.2.3 with REST/CRUD and then updated the link at the end of that post. [...]

Comment RSS · TrackBack URI

Leave a Comment

Name: (Required)

E-mail: (Required)

Website:

Comment: