• Home
  • About
Blue Orange Green Pink Purple

Simple Comet demo for Ruby on Rails

Posted in code. on Thursday, November 20th, 2008 by Chris Hulbert Tags: comet, rails, ruby
Nov 20

Here's the script from a talk I gave yesterday at Ruby on Rails Oceania Sydney.

Hi all, I'm Chris Hulbert. During the day i work as a C# programmer, but don't hold that against me. I'm new here so be nice.
I'm here to talk about Comet. Comet is a handy technique for allowing the server to notify the client about any event. Yes, welcome to windows 311 programming again, we're talking event driven programming, but for websites.

If you've ever had an application that needs a real-time update of something, like a stock price, you'd be familiar with using a 'periodical updater'. The periodical update ajax method is like on a car trip when the kids are saying every minute 'are we there yet?'. When the dad cracks it and says 'stop asking! i'll tell you when we get there', he's basically telling them to become Comet programmers.
Now there's a few ways to do Comet, i'm just going to cover one. You'll have to forgive all atrocities performed in the name of simplicity here.

So here's my bare rails app. I've made a controller which has the index action, and an action that responds to the comet request. These two files [the controller and the view], that's it. The 'event' in this application is the update of a text file called 'comet.txt'.

Lets look at the index page, which is the 'client' end of things.
Before we look at it, i have to give credit to a PHP comet demo. But we all dislike PHP here dont we, so nobody will look it up right?

index.html.erb

<html>
<head>
  <script src='/javascripts/prototype.js'></script>
  <style>body {background:#444;color:#ccc;font-family:trebuchet ms;} strong {color:#fff}</style>
</head>
<body>

  <p><strong>Comet Messages:</strong></p>
  <div id='comet_target'></div>

  <script>
    var timestamp=0; // Remember the timestamp of the file that is being watched
    function comet_connect() // Start a comet request, this is where the magic happens
    {
      new Ajax.Request('/comet/comet_request', { // Here starts an ajax call; Comet is ajax in drag
        method:'get',
        parameters: {'timestamp':timestamp}, // Notify me when the file is newer than this
        onComplete: function(transport) { // If you will, this is the event handler or delegate
          var json = transport.responseText.evalJSON(); // Unpack the json response
          timestamp = json.timestamp; // Remember the new timestamp of the file
          $('comet_target').innerHTML += json.msg + '<br />'; // Display the response message
          setTimeout("comet_connect()",500); // Wait for the next event
        }
      });
    }
    comet_connect(); // Start the first comet request
  </script>
</body>
</html>

Now lets look at the comet_request action. Basically this action holds the HTTP connection open and waits for the file to change, then it sends the notification.

comet_controller.rb

class CometController < ApplicationController

  def index
  end

  def comet_request
    # Figure out where the comet.txt is
    @filename = RAILS_ROOT + '/comet.txt'

    # Wait for it to change. We know when it changes because
    # the timestamp on the file will change
    while params[:timestamp].to_s == File.mtime(@filename).to_s
      sleep 0.1
    end

    # Create the notification to send to the client
    @msg = File.readlines(@filename)
    @timestamp = File.mtime(@filename)

    # Pack and send it
    @json = "{'msg':'#{@msg}','timestamp':'#{@timestamp}'}";
    render :text=>@json
  end
end

Ok that's all there is to it. Now lets see if its going to fail in the middle of a presentation.
Notice how it sends a message to the client whenever i change and save the file.

Download the demo

Thanks for being a great audience and listening to my ramblings

If you ever decided to use Comet in a production application, use something a bit more robust than what i've described above, such as Juggernaut.

4 Comments

  1. igor on November 20th, 2008

    too simple, why you didnt used periodic update function from protoype?

  2. Hugh on November 20th, 2008

    Hey Chris, thanks for giving this talk at RORO and making these notes available :)

  3. Mike Berrow on November 21st, 2008

    So "comet_request" on the server side sits there in an infinite loop waiting for the file to change?
    Correct me if I'm wrong. but won't that jam the server and prevent any other requests from being serviced while it is in that loop?.
    – Mike

    Chris: Spot on mate! That's why i say you should use Juggernaut if you ever did this for real.

  4. Markus on February 10th, 2010

    The link "Look at comet_controller.rb in pastebin" leads to "Unknown post id, it may have expired or been deleted" at pastebin



Leave a Reply

Chris' Babble

  • About
    Hi, i'm Chris Hulbert, a software guy from Sydney Australia.
  • Categories
    • code
    • Portfolio
    • Uncategorized
  • Recent Articles
    • How to implement DES and Triple DES from scratch
    • How to use Cookies in Struts 2 with ServletRequest and ServletResponse
    • How to use sessions with Struts 2
    • Using Quartz Scheduler in a Java web app (servlet)
    • Javascript date picker that Doesn't Suck!(tm)
    • Using Oracle XE with Hibernate


  • Home
  • About

© Copyright Chris' Babble. All rights reserved.
Designed by FTL Wordpress Themes brought to you by Smashing Magazine

Back to Top