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:
-
def update
-
last_update = Time.parse(params[:timestamp])
-
# locate all of the entries created since the last update
-
@entries = Entry.find(:all, :order => ‘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’, :object => 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:
-
<body onload="go()">
-
<p>This page updates automatically!</p>
-
<br/>
-
-
<div id="spy-list" class="spy-list">
-
<% if !@entries.empty? %>
-
<%= render :partial => ‘entry’, :collection => @entries, :locals => { :hidden => false } %>
-
<% end %>
-
</div>
-
</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).
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).
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
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. [...]