Archive for the ‘Javascript’ Category

Comet with Rails + Mongrel

Tuesday, May 8th, 2007

In my last post I described how to create a mongrel handler. I said you might want to do this for optimization purposes, but my own interest came about in an attempt to solve the server-push problem with Rails.

Comet is the term that seems to be catching on for server-push via XmlHttpRequest. Possible applications include chat clients or a stock ticker. Anything that wants constant updates will be both responsive and less demanding of server resources if it waits for data to be pushed to it, instead of opening a new status query every few seconds.

Since the server can’t initiate a connection to the user’s browser, the only possible solution is to have the browser hold a connection open indefinitely, waiting for an update. Since Rails is single-threaded, however, this means that one whole server instance would be tied up by this connection - clearly infeasible in almost all situations.

You might say, “Why not have another small server listening on a separate port to hold on to these push-status connections?” Good idea - except that XmlHttpRequest won’t let you connect to another port. This is because the port is considered part of the hostname, and connecting to another hostname from within the javascript sandbox would be a big security no-no. (It would be trivially easy, for example, to inject a little javascript into a site which caused all of its visitors’ browsers to start hammering another unrelated site as soon as they visited the homepage.)

Juggernaut gets around this with a little hidden Flash component. This is a nifty idea, but for me it is unappealing because Flash is not readily available for my platform (Ubuntu AMD64). More importantly, I’d prefer to avoid building technology that depends on a proprietary plugin built by a monolithic, old-fashioned (i.e., shrink wrap) software company.

So holding open connections to Rails won’t work due to its controller lock. But as was demonstrated in the previous entry, a mongrel handler won’t have that problem. I’ll extend the auction example shown there to use server-push.


require 'active_record'

class StatusHandler < Mongrel::HttpHandler
   def process(request, response)
      id = request.params['PATH_INFO'].slice(1, 20)
      current = request.params['QUERY_STRING']

      while status(id) == current do
         sleep 0.2
      end

      response.start(200) do |head, out|
         head["Content-Type"] = "text/html"
         out.write status(id)
      end
   end

   def status(id)
      connection.select_value("select status from auctions where id=#{id.to_i}")
   end

   def connection
      ActiveRecord::Base.connection
   end
end

uri "/status", :handler => StatusHandler.new, :in_front => true

This assumes your auctions table has a field named “status,” which I’m using as an integer, but any type should work. http://localhost:3000/status/1 now delivers just one value, the status. Where it gets interesting is something like http://localhost:3000/status/1?100, assuming that the status of auction id=1 is currently set to 100 in the database. Now, the connection will hang and wait for the value to change. (You’ll see the database queries in development.log, but no web hits.) Pop open a sql shell and run “update auctions set status=101″ and the connection will resolve immediately, printing out the new value.

Here’s a simple example of making an ajax call to this url from within a page:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
   <%= javascript_include_tag :defaults %>
</head>
<body>
   Status is now: <span id="status"></span>

   <script language="javascript">
      function respawn()
      {
         new Ajax.Updater('status', '/status/1?' + $('status').textContent, { onComplete: respawn });
      }

      respawn();
   </script>
</body>
</html>

Experiment with updating the status value in the sql shell and you’ll see that the page always updates instantly. To watch the connections, open the Firebug console, click Options in the upper-right, and make sure “Show XMLHttpRequests” is checked. Reload the page and you’ll now see a POST each time you update the status. There will always be an active one at the bottom, waiting, waiting for the status update.

And there you go. Server-push connections with only Rails and Mongrel.

Update: Mere minutes after I finished writing this article, I came across Shooting Star, a Rails plugin for adding Comet to your apps. So far this looks a little heavy-weight for my purposes, and somewhat platform-dependent so far - not to mention that they push the meteor metaphor a bit far in their method naming. Still, this may be a more robust solution than my little hack, so check it out. If anyone has tried Juggernaut, Shooting Star, and my hack, I’d be curious to hear a comparison.

Javascript Text Editor

Friday, April 20th, 2007

Here’s a source code editor I wrote in javascript, inspired by CodePress. Feel free to snag and use in your application or modify to your needs. Syntax highlighting and indenting for Ruby is hardcoded, but it could easily be modified by swapping out ruby_syntax.js with your own class. I used Prototype just out of habit, but it could be factored out very easily - I just use it for a couple of simple things like Event.observe.

One thing that really struck me working on this is just how powerful javascript and DHTML have become. I mean, writing a programmer’s editor is hard, right? But I cranked this out in a few evenings. And yeah, I know it’s far from full-featured; but it really blew me away just how easy this was. The only part that was even mildly challenging was handling selections.

I’ve worked with a number of different display paradigms over the years. Early on I was doing character-based output, drawing little boxes and menus and so forth using the upper 127 ASCII line drawing characters. This was great because it was so easy, mostly because everything fit onto a grid.

Later I started working with graphics by manipulating the raw pixels. It took a pretty massive amount of time to do something as simple as make a button, let alone something complicated like a scrolling panel or tabs.

A few more years passed and now there were various sorts of GUI toolkits. I started with hideous, barely usable ones like Motif and the raw Win32 libs. Later I moved on to more enlightened toolkits like Qt and GTK. The box model they offered for packing widgets, coupled with some good visual design tools, made the process of building the display portion of your app pretty reasonable.

Still, it was difficult to mix freeform drawing like lines or shapes with the box-model widgets. And either way, it was just nowhere near the ease of working with those simple character-based displays. That’s the price of progress though, right?

Nope. Somehow - and I’m not sure how or when it happened - DHTML managed to evolve into a combination of the box model (for auto-adjusting layouts) and the canvas model (for freeform drawing). And somehow, working with it, I had a strange sense of deja-vu: working with DHTML is very pleasantly reminiscent of the good ol’ fashioned character grid from my old 80×24 text mode programs.

Maybe because, at it’s core, HTML really is just a bunch of characters. But it’s divided into container nodes that can easily be positioned however, including using box model stuff to get them to line up neatly and dynamically resize with their content. And then it’s like a canvas in that you’re free to position things however, breaking them out of the grid if you want. And then when I see the amazing things you can now do with inline SVG, all I can say is: the sky’s the limit.

Prototype: Sliced Bread, or Devil’s Spawn?

Wednesday, January 24th, 2007

People like to bitch about prototype.js, usually because it extends Array and Object in ways that are incompatible with a lot of existing code, including other add-on libraries. I fully agree with this criticism, but I have yet to find another alternative. Prototype fills a very important niche in the javascript ecosystem: a small, simple, succinct library that lets you do 95% of the things you’d want to do in a modern Ajax app.

Here are some other javascript toolkits. Mind you, these are not all trying to provide equivalent functionality. But I think it’s fair to include them all on the same list, because they are all trying to provide tools to make Javascript a more powerful language, and one more suitable for creating the types of web apps that most people want to make these days.

Mochikit is the one I’m most familiar with. It’s a great toolkit, and kind do all kinds of cool stuff that Prototype doesn’t. But, most of the time I just want to do a simple ajax call, or really minor DOM manipulation. Mochikit just feels like massive overkill in those cases.

This could be intention - Mochikit is supposed to be a heavy-weight solution, which is what you need sometimes. But being heavy-weight means that it’s got that namespaced, heavy-handed, verbose feel that I associate with Java and Python. For example, look at what you need to do to make an Ajax call in Mochikit:


var deferred_obj = MochiKit.Async.doSimpleXMLHttpRequest('/some/url');
deferred_obj.addCallback(updateDiv);
function updateDiv(result) { $('mydiv').innerHTML = result; }

Compare to Prototype:


Ajax.Updater('mydiv', '/some/url');

Aside: I’m no Mochikit expert, though I’ve used it on a few projects. If someone has a better way to write the example above, please leave a comment.

Aside 2: The technique above could more correctly be called AHAH.

You could go on and on about how Mochikit is more powerful, that its deferred object framework offers all kinds of possibilities for unusual ajax calls and other kinds of javascript magic. All that is true. But then there’s the fact that, 99.9% of the time, all you want to do is fire off an ajax call and update a div, or maybe call a function to process the results.

Easy things should be easy to do. When a “powerful” tool makes the easy case hard, I get suspicious. For code, easy means easy to write (which means, easy to remember: I don’t want to reference the docs every time). But it also means easy to read and understand later, and for that you want to be succinct and explicit. Reading the prototype code I can see that the line has something to do with ajax and something to do with updating. Simple and unmistakeable.

The best tools are ones that make the easy case easy, but still offer the power to do more complex and unusual things if you want to dive in a bit deeper. So I guess you could make a Prototype-style wrapper for Mochikit, with simple helper classes like Ajax.Updater to export a succinct interface to the powerful concepts that Mochikit offers, and that should be the best of both worlds.

As for Prototype, I’m certainly not enamored with it. In fact, I’m really hoping for is some other small library will come along and fill the same niche as Prototype, but do it better. In the meantime, Prototype is the best in that niche, so I’ll keep using it.