Apr 14

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:

def update
  last_update = Time.parse(params[:timestamp])
  # locate all of the entries created since the last update
  @entries = Entry.find(:all, :o rder => 'created_at ASC', :conditions => [ 'created_at > ?', last_update.to_s(:db) ]);
  if !@entries.empty?
    render :update do |page|
      for entry in @entries
        page.insert_html(:top, 'spy-list', :partial => 'entry', :o bject => entry)
        page.visual_effect :highlight, "spy-item-#{entry.id}"
      end
    end
  end
end

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

var updateInterval = 5000; // update every 5 seconds
var timestamp = new Date().toUTCString();
var timer;

function go() {
  timer = setInterval('update()', updateInterval);
}

function update() {
  url = "/spy/update";
  new Ajax.Request(url, {
               asynchronous: true,
               method: "get",
               parameters: "timestamp=" + timestamp,
               onSuccess: function(request) {
                 timestamp = new Date().toUTCString();
               }
  });
}

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:



This page updates automatically!


<% if !@entries.empty? %> <%= render :partial => 'entry', :collection => @entries, :locals => { :hidden => false } %> <% end %>

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).

  • john
    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
  • Ben
    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).
blog comments powered by Disqus
preload preload preload