just a dude abiding

Multiple Sinatra .90 applications in one process

I recently started work on a new application based on the current Sinatra edge code. I’m not new to Ruby, but I’m definitely new to Sinatra. So I thought I’d start a small series of posts based on the things I find either interesting, or difficult. Today’s post probably falls into both categories.

One of the things that drew me to Sinatra was the absolute simplicity in it’s approach to web apps. One of the keys to this simplicity is leaning heavily on Rack. Rack provides a variety of what they call Middleware, small bits of code that insert themselves into the request/response process, handling things like caching, session management, or even JSON parsing.

Now that we’re through with the background, let’s hit my find of the day.

As I started working I found that I felt more comfortable with my application being defined inside of a class instead of just floating around in files (the default method of building a Sinatra app). It turns out this is one of the lesser documented parts of the new Sinatra .9 release. (In all fairness this seems to be due to the fact that a lot of the infrastructure that allows this to happen is either brand new, or heavily refactored in this release)

It turns out I could do a whole lot more, such as making each portion of my application it’s own standalone Sinatra application, then using some Rack Middleware to mount each portion into it’s own URL space. Why would I want to do this? I think it will make for a very extensible, and potentially scalable infrastructure. All of that aside, let’s see HOW you do this!

For starters you need to define a class for your application to live in.

There’s a simple set of classes that function as little application stubs. Notice that we require sinatra/base instead of just sinatra. This is one of the new things in the .9 release. By requiring just sinatra/base we get all of the sinatra goodness, without any of the intrusive top-level methods. Since we’re going to encapsulate our application in our own classes, this is perfect for us! For these little applications to fully work we’ll have to define some views, which I’ll leave up to you (or you can check the full project files at GitHub at the end of this post).

Now here is where we define our Rack magic. We’ll create a config.ru file, which uses what’s called RackUp syntax to specify some options for Rack compliant servers to use to configure and start our application. For this example I’m using Thin, but you can use whatever you prefer!

Up until line 15 it’s pretty standard boilerplate for getting any Sinatra application going, but after that is where things get interesting. Rack automatically includes the URLMap Middleware which gives us access to the ‘map’ method. This method takes two parameters, a URL prefix, and a block specifying that applications configuration. We could do any configuration we can do at the top level inside of that block, giving some pretty powerful per-application configuration.

And that’s it! Start it with thin -p 4567 -R config.ru start, or the equivalent. You should be able to navigate to / and see your first index, and /blog and /blog/list respectively to see their content. Notice how our Blog class never uses the /blog URL prefix anywhere. This would let us pass the exact same class into a different application, at a different URL space, and the application wouldn’t be any wiser for it.

Want to see the whole thing already setup? Check out the GitHub link below for the full sample application.