Monday, December 29, 2008

Sinatra Dances on Passenger's Stage

I wrote briefly in my last post about how I've been working with sinatra quite a bit lately. After some great experiences at work, I decided to move my homepage over to sinatra from rails. It was totally inane to have the site written in rails in the first place, but I'd been learning the framework at the time and when you have a hammer...well, you know.

Anyway, I learned quite a bit about deploying a sinatra app on passenger as well as using passenger for development of sinatra apps and I figured I'd talk a bit about that. One great thing about passenger is its ability to serve any rack application. Rack is a tiny little framework that acts as a sort of standard for dealing with http requests and sinatra supports rack. This means deploying a sinatra app on passenger is pretty simple, but I had to poke around a bit to get the wheels running smoothly. Let's first look at my application layout.



We'll look at each of these files a bit closer. First and foremost, we've got the drewolson.rb file. This is my sinatra app, which we won't go into now, but remember that your sinatra app should sit at the root of your directory structure. You can also see that I have 3 subdirectories. The first is public, where you throw any static files (like images, stylesheets or favicons). The next is the views directory, which is pretty self-explanatory. Throw your view files in here.

Last but not least is the test subdirectory. This is where the tests for my sinatra app reside. Sinatra actually provides you with some pretty nice testing tools, and I'll just show you my test_helper.rb which all my tests require.



Ok, now onto the deployment fun stuff. There are two files that are key to deploying sinatra apps on passenger: config.ru and Capfile. Capfile is my capistrano deployment script and config.ru is my rackup file. Let's look at config.ru first.



I tried several variants of this file, but this is the only one that works for me. Notice that you have to explicitly state where you app_file is located as well as where your views directory sits.

Next up, let's look at my Capfile.



Again, this is super simple when compared to a standard rails Capfile. Notice that we overwrite deploy:restart. All we have to do with passenger is touch a file. Note that this also assumes you have ssh access to your server and that you're using git as your version control system.

The last piece of the puzzle is setting up a virtual host for apache. Now, you've probably already done this before but just to be complete I'll show you my virtual host for this application.



Yes, that's it. Seriously. Assuming you've enabled the site in apache, all you have to do on your first deploy is run:

cap deploy:setup
cap deploy

Bam, you're up and running with a sinatra app on passenger. But that's not all. One thing that I struggled with when getting this all working was constantly deploying, checking the app, fixing the config.ru, deploying, checking the app ... All this could have been avoided if I'd simply been developing on passenger locally and using it to run my rack based sinatra app locally before deploying. Well it turns out this is super simple. You can use the awesome passenger prefpane if you're on OS X. Simply install it, point it at your directory, and you now have a local copy of your sinatra app running on passenger + rack. How sweet is that?

Update:

It seems that newer versions of sinatra and rack break these instructions. They are verified working for rack 0.4.0 and sinatra 0.3.2. Updated code snippets to reflect this.

1 comments:

scudco said...

This is pretty helpful stuff.

Also I just stumbled onto Capinatra