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.

Tuesday, December 23, 2008

Mashup your RSS Feeds with ruby + sinatra + pipe

I've been doing some build work lately and I stumbled upon a situation last week where I needed to take a bunch of RSS feeds, aggregate them and filter only the specific items I wanted. This actually manifested itself with continuous integration boxes. We have a lot of CI boxes running a lot of builds but each team is only interested in several of these builds.

One option is using something like CCMenu, but I actually needed a consumable RSS feed for use by another service that displayed build status is a very big, readable way (for a monitor in the team area). This aggregation and filtering of RSS feeds is, in fact, exactly what Yahoo Pipes does. However, these are all internal feeds, so Yahoo Pipes wouldn't work for me here.

Lately, I have been toying with sinatra, a great little web framework in ruby. I decided to write a tool that could be used in conjunction with sinatra to get me my RSS feed aggregation and filtering. That tool is called (not surprisingly) pipe. Below is the code for creating a simple feed containing all the ruby related articles on ycombinator and the clojure related articles on the programming subreddit:



You can install pipes like so:
- gem sources -a http://gems.github.com
- sudo gem install drewolson-pipe

The documentation is here. Enjoy.