Contributing to guard-rspec
March 01, 2011As is probably apparent from my last post, I'm interested in improving the front end parts of my Rails apps and smoothing out the rough edges of working with Heroku. Some big changes are coming in Rails 3.1, but in the meantime I've been looking at ways to make the process of asset compilation and packaging easier. The recent rewrite of this site is the first time I used Sass, and it's great, but it adds another step to getting CSS ready for deployment. The Sass gem has a command line tool to compile a Sass file into CSS. It allows you to watch a directory for changes and compile them automatically. Sadly, if it doesn't have access to FSEvents through RubyCocoa, it will constantly poll your disk for changes, and since I use Ruby 1.9.2 with RVM, this is the case I found myself in. As it turns out, wanting to improve the process for Sass led me to something entirely different.
I looked around for a better way to listen for file system events with Ruby 1.9.2 and discovered Watchr, which, when coupled with ruby-fsevent, allows a generic mechanism for running scripts in response to file system events. While reading about Watchr, I started to notice people mentioning a slightly newer alternative called Guard, which uses the confusingly not-identical rb-fsevent. The nice thing about Guard is that it runs gem extensions which encapsulate the logic for a particular task. The "Guardfile" simply invokes such a gem and tells it which paths to watch.
Guard has quite a few of these gems already, and the first to catch my eye was guard-rspec, a flexible alternative to ZenTest/autotest. I tried it out and discovered that it was a bit restrictive in which command line options you could pass to RSpec. Instead of allowing you to pass arbitrary arguments, it allowed only a few of RSpec's options via its own API. These options were then redundantly curried to RSpec. I prefer my RSpec output in the nested format, and because of this restriction guard-rspec wasn't ideal for me. I added a feature request for it on the GitHub issue tracker, but then I remembered Zach Holman's recent tweet: "Marginal programmers +1 an issue. Real programmers patch the issue." So that's exactly what I did.
I'd made a few minor contributions to other projects before, but this time I spent some decent time working on a revised API for guard-rspec which allows you to pass arbitrary arguments to RSpec. It took a few days discussing my changes with the two authors, and ultimately they refactored a lot of my code to their liking, but it felt great to be a part of a significant improvement to a project that lots of other people use. And as always, my Ruby skills are that much more deadly after sharpening them on the open source grindstone.
My changes are included in the just-released guard-rspec 0.2.0. Check it out!