Practical Ruby Projects

My Ruby book Practical Ruby Projects: Ideas for the Eclectic Programmer is in stores!


(Practical Ruby Projects)

I’ve been writing for the past year, and I’m crazy about the result. This is the sort of book that I love to read, and hopefully that shines through.

Practical Ruby Projects is based on a few ideas:

  • “Hands on” is always better.
  • You can cover more if you trust your reader to know the basics.
  • Programming can be creative and exciting.
  • Getting started is hard. Anything that makes that easy is good.

This book covers a lot of projects (all done in Ruby, of course!):

  • Animation
  • Music
  • Simulation
  • Turn Based Startegy Games
  • RubyCocoa
  • Genetic Algorithms
  • Implementing Lisp
  • Parsing

PS- All the source code is available under the MIT license!


National Album Recording Month 2007

Holy Album Recording Month, Batman!

This blog post is oh-so late, but my server crashed taking down both this blog and the National Album Recording Month webite. What a mess!


(Let me sing you a little song, it’s about National Album Recording Month…)

But we’re back up, and National Album Recording Month is ready to go. Last year’s participants are re-signing up and we’re looking for new blood. Here are the rules:

  • Record 31 minutes in the 31 days in May.
  • Pick a title and make some cover art.
  • Anything goes. Original songs, covers, spoke word, comedy, or essay. Just make an album!

It’s time to put aside our fears, ranging from “I don’t know anything about music” to “I don’t have the time to do it right.” Wouldn’t you rather have recorded an album by May 31st than made excuses?


(Putting aside your fear means willingness to look like a total idiot.)

The greatest thing about NARMo you can actually do it! You could finish in just 36 minutes (a straight 31 minute recording session and 5 minutes to draw a cover on a cocktail napkin). Of course, the best albums will take a little longer. ;-) But seriously, over 20 people finished last year and we recorded hundreds of minutes all together.

Hope to see you on the NARMO sign up page! Spread the word.


Oh Crap

Japanther plays a show with the Aquadoom synchronized swimmers.


One Step Back

Does anyone know why the recently released Core Doc for Ruby 1.8.5 contains a flood of classes from the Standard Library (which is also documented separately)?

It’s resulted in a serious loss of usability. Now when I need documentation on the core classes that really matter (classes like Array, Class, Enumerable, File, Hash, IO, Regexp, String, and Thread), I have to wade through a mess of DRb, Generators, IXMLDOM, Net, RDoc, REXML, RI, RSS, Resolv, Rinda, RubyToken, SM, SOAP, Test, WEBrick, WSDL, XSD, YAML, and Zlib.

All of which are great (except SOAP and WSDL — ugh ;-). I just liked it better when they were documented separately in the Standard Library docs.

Some kind of fancy AJAX search interface to the RDocs might take the edge off here, but I’d still like to be able to browse just the most important classes. I hope we don’t lose that ability forever.

For some perspective, here’s the number of classes (+/- one or two) documented in the Core RDoc for the past three releases of Ruby.

1.8.3: 167
1.8.4: 181
1.8.5: 1325

Yikes!


Mongrel Comet Update

If you’ve been looking to do Comet work using Ruby and Mongrel, I might have some good news.

I’d previously reported that my code to add Comet support to Mongrel required a seperate URL handler at a different mount point for each persistent connection because of some mysterious threading issue.

Looks like I may have been misunderstanding what was going on. In fact, Joseph McDonald reports that it works just fine… provided you remember to respect your browsers allowed number of connections. I’m not sure why I’d forgotten about this during testing. From Wikipedia:

Browsers pose a further limitation: section 8.1.4 of the HTTP 1.1 spec states that “A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy”, and this recommendation is in fact followed by the most common browsers, including Internet Explorer and Firefox. Holding one connection open for HTTP streaming tends to create performance issues for AJAX applications, such as inability to kick off a new user-initiated data request while a series of images are being loaded. This is often worked around by creating a distinct hostname for push connections (even with a single physical server).

My First Writing Check

I meant to make this post a long time ago. But check it out, my first writing check (from my If It’s Not Nailed Down Steal It article, which I’ve just noticed is the first search result for that phrase =).


(Am I a real writer yet? Or do I need to wait for the book to come out?)

I hope it’s the first of many to come. In other writing news, the first chapter of Ruby Projects for the Curious Programmer is due this Monday and I’m almost done with it!


Making Ruby into PHP

Sometimes a web framework is just over kill. Maybe it’s a one off dynamic page, maybe you don’t want the memory footprint of a whole framework running for only a small component of your whole site.

mod_ruby and eruby can get you a lot of what PHP gives you if you’re into that and don’t mind the setup. There’s the added perk that you won’t have to write PHP.

But what if you want something similar, but quick and simple and you’re willing to use CGI? Here’s a neat little trick.

First save this text into a file called “rubyhp.rb” in your cgi-bin directory.

require 'erb'
require 'cgi'

cgi = CGI.new
print "Content-type: text/html\n\n"
print ERB.new(DATA.read).result(binding)

Leave this file unexecutable, so your web server won’t serve it. Then create your PHP style Ruby file like this.

#!/usr/bin/ruby                                                                 
require 'rubyhp'
__END__
<html>
 <body>
  <% cgi.params.each do |key, value| %>
   <%= key %>: <%= value %><br />
  <% end %>
  <% if cgi.params.empty? %>
   Sorry, please enter some cgi parameters. How about "?foo=baz"?
  <% end %>
 </body>
</html>

Name this file “test.rb” and save it in your same cgi-bin directory. Make it executable and you’re done. You can write whatever erb you want after the __END__ line, without needing to worry about setting up anything fancy. And you have access to a parsed CGI object through the variable ‘cgi’.

Does CGI still have a place in modern web work? I’m don’t know. But I do still use it for quick dynamic pages on cyll.org like the Computer Science Bandname Generator. This little trick makes life a little easier for me when I do.


Chatting with Pune Ruby

Satish Talim, of the PuneRuby users group in Pune, India, is interviewing people from the Ruby community. So far he’s interviewed my friends Peat Bakke and Phil Tomson, as well as Bruce Tate and James Edward Gray II.

Satish has also interviewed me. You can read the results of my interview here. This is a pretty neat idea. Each new interview will be posted at PuneRuby.


The Mongrel Comet

Comet is a javascript technology used to receive events without AJAX polling. You can read about Comet on Wikipedia.

Mongrel is an excellent HTTP server for Ruby. Have a look at its cute dog.

While I was playing around with a Ruby based DHTML turn based strategy game a few weeks ago, I found myself struggling with latency. I was using an AJAX polling mechanism, and with all the game logic on the server side, things felt laggy. There were any number of options I could have tried. And, in fact, in the end, I just ignored the problem.

However, in the process I read about Comet and began to wonder how hard it would be to add it to Mongrel.

It turned out to be suprisingly easy… after a fashion.

COMET_FORMAT = "HTTP/1.1 %d %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunke\
d\r\nConnection: close\r\n".freeze

class HttpResponse
  def comet(type,  status=200)
    write(Const::COMET_FORMAT % [status, HTTP_STATUS_CODES[status], type])
    write("\r\n")
    return HttpComet.new(self)
  end
end

Above, you can see the first thing we do is add a comet() method to our response object, this returns an object we can stream our data out through. We’d use the HttpComet object like this, writing each integer up to 100 to the connection:

class ExampleCometHandler < Mongrel::HttpHandler
  def process(request, response)
    comet = response.comet("text/plain")
    (0..100).each do |i|
      comet.write("#{i}");
      sleep 1
    end
    comet.close
  end
end

The code that makes this all work lives inside HttpComet. It uses “chunked” HTTP transfer to send portions of the data along at a time.

class HttpComet
  def initialize(response)
    @response = response
  end

  def write(data)
    size = data.size
    @response.write(sprintf("%x;\r\n", size))
    @response.write(data)
    @response.write("\r\n")
    @response.flush
  end

  def close
    @response.write("0;\r\n")
  end
end

Each chunk starts with a number of bytes in hex, followed by an \r\n, then the payload. A chunk of size 0 indicates the end of the file. And that’s all there is.

Now, there’s one problem. The way I’m doing this has the side effect that only one user can be Comet streaming from any particular handler instance. Registering another instance of the same handler at a different URL and using some kind of redirect to get each user to their own URL and handler can work around this, but it’s ugly as sin.

But hey, I learned about HTTP chunked mode!

[Code Available Here]

Update: Oh, it’s worth mentioning, getting events to actually trigger on receipt for all platforms is tricky, so instead of just sending data, often Javascript is loaded into an iframe. You can see an example of this in the source.


FOSCON Strikes Back

I feel good saying that FOSCON was a raging success. Serious congratulations are in order to all the PDX.rbers that made it happen. You guys are amazing.

I made my way to FreeGeek with the walking tour group. There were about eight of us and we stopped for a pint on the way. I figured this would be the majority of the crowd, so I was stunned when we arrived and people were already packed in so tight that they were overflowing out of the room. I’ve never seen FreeGeek so full.

My talk went well, and hopefully this will be the first of them that we’ve successfully managed podcast (out of four; our success rate is not so good =). I’ll post a link as soon as that’s up. In the meantime, you can find my slides, code, and other stuff about a DHTML turn based strategy game written in Ruby here.

It was great to meet everyone! Events like this help remind us just how weird and wonderful the Ruby community is.


Page 1 of 2