Wednesday, June 3, 2009


‹prev | My Chain | next›

With 150 of 200 Cucumber steps defined and passing, it is time to start thinking about deployment. It doesn't hurt that I need to do some research for an upcoming presentation.

Ultimately, I think that I will end up deploying to a Thin or Passenger server, which will hand off most requests to my little Sinatra app. To do either, I can use Rack.

Sinatra already uses Rack for much of its innards. Still it can't hurt to make sure that I can run with Rack. As with any Rack application, I create a file. This file is especially sparse for Sinatra due to the already tight integration of the two. All I need to do is require my app and run it:
require 'eee'
run Sinatra::Application
I can verify my minimalistic Rack configuration with the rackup command (no arguments) and navigating to the meals in 2006 URL on port 9292 (the default for rackup). I have a single meal from 2006 in my CouchDB database, which I see on that page:

Nice! Everything looks to be in order. I do not have much data in my development DB, so I will not be able to smoke test much. Maybe just a link or two. The navigation between years seems to work—I can click on the the year 2003 and see "Almost French Onion Soup" listed as a meal that we prepared that year. But when I click that meal, I get this error:

uninitialized class variable @@db in Eee::Helpers? Sounds like fun.

To aid in isolation testing, I define all of my helpers in a module with a namespace of Eee::Helpers. I then mix those helpers into the Sinatra app's helper via the helpers block:
helpers do
include Eee::Helpers
Those method ought to have access to the Sinatra class variables, which are defined via Sinatra configure blocks:
configure :development, :production do
@@db = "http://localhost:5984/eee"
The helpers ought to have access to class variables (at least in my understanding), but clearly they do not.

OK, so let's ask the current object what class variables are available. In the topmost method of the call stack, I raise the answer to that question:
    def _db
raise self.class.class_variables.join(", ")
After restarting Rack, I get my answer:

@@db is a class variable in the current scope. So what gives? Best I can figure (and I can only guess at this point) is that either the helpers or the configures define things on the eigenclass of the Sinatra app, while the other is on the class proper. I may have to stick with my guess because the Sinatra code includes some heavy meta-programming including sub-classing self (class << self) and class_eval. I think I'll risk programming by coincidence and guess there's an eigenclass involved somewhere in there.

If that is the case, then I ought to be able to ask the class for the value of the @@db class variable and be done with it:
    def _db
self.class.send(:class_variable_get, "@@db")
Indeed that does work.

It's been an interesting night looking through Sinatra code. Interesting but not much progress with Rack other than getting it running. Tomorrow I will make sure that I can run with both Thin and Passenger and then explore some Rack middleware.


  1. Deployment should always be the *first* thing you should think about. Keep up with this series. Definitely some good reading in here.

  2. Thanks!

    Good point about when to think about deployments. Bitter (and sadly repeated) experience has taught me that leaving deployment considerations until the last minute will cause grave problems.

    I have given it some consideration before (, but not nearly enough. This post should have come *much* sooner than this.