In the Fall, outside.in took the plunge and committed to an aggressive overhaul of the back-end of our system. We rewrote the codebase, which was PHP, from scratch in Ruby, using the ever-popular Rails framework. In addition to the change in code, we also decided to switch our back-end database from MySQL to Postgres. And we gave ourselves just 10 weeks to do it. I should also mention that, at the time, only a third of our dev team had practical experience with Ruby on Rails. (I should also mention here that we are currently hiring great Rails developers.)
So why did we make the switch?
Over the first 10 months or so of outside.in’s life, the primary development focus was on proof-of-concept prototyping. Our initial goal was to just build something that worked, and at the time we weren’t sure what parts of it were going to gain traction and really stick around, and what parts weren’t going to be important later on. Making quick changes in direction is of course at the heart of agile development, and we did an excellent job of building a system that allowed us to try new features out very quickly. Still, over time the code hardened somewhat and as we went along we found more and more time was going in to administrative coding. We decided we needed a framework to consolidate the code and simplify further development.
Christian, the only developer on the team that had prior Rails experience, advocated that we look at using Ruby on Rails for the new and improved outside.in. I had had enough experience messing around with simple programs in Ruby to realize that it’s a beautiful, expressive language, and I knew that Rails was taking the web 2.0 world by storm. Christian started spending about a day a week porting outside.in to Rails to see how feasible a full transition would be.
It’s worth noting at this point that another big motivation for migrating our back-end was that ever since the Where 2.0 conference in May, we had been really excited to use Postgres so we could take advantage of its excellent PostGIS extensions for doing geography-based queries, which are obviously very important to outside.in. The GeoRuby gem and Spatial Adapter rails plugin, which would give us a lot of free GIS-related functionality in Rails gave us another strong reason to look at RoR.
We decided Rails was going to work for us. The benefit of hindsight allowed us to rework parts of the database back-end and code architecture that hadn’t worked very well before when they had been developed ad hoc, and to take advantage of Rails’ Model-View-Controller (aka MVC) separation to consolidate code that had before been spread out and duplicated over many files. The excellent unit and functional testing framework in Rails is one of many useful features that we got for free that would have been time-consuming to build ourselves in PHP.
How’d it go?
Switching programming languages (and training the dev team on a new language), upgrading to a full-fledged framework, and changing database back-ends are all intensive tasks. Any one of them would have been a significant challenge on its own, but trying to do all three at once was especially difficult. Programming languages tend to overlap heavily in the control structures that are used, so the primary hurdles involved in learning Ruby were learning its syntax and the concepts of blocks and iterators. The syntax is pretty easy to learn, since Ruby’s syntax is so minimal it never really gets in your way, but it took a while to get the hang of blocks and yields. IRB is a godsend here because it makes it so easy to drop into the terminal and test something out that there’s no excuse for superstitious programming. Rails is more difficult because it’s so powerful; a lot happens “magically” and it can take a while to understand how all the pieces interact.
Switching hosting providers was a lot less painful than expected, thanks to EngineYard, the Rails-specific, slice-based hosting company that we ultimately chose to go with. EngineYard handles deployment of one’s app, including writing custom deployment recipes, and they were very responsive both on the phone and through their ticket-based support system. I’m very happy to be doing business with them.
All in all, it’s a testament to the flexibility of Ruby on Rails — not to mention the talent of the excellent programmers we have here — that we were able to bring over a feature-complete (and improved!) version of outside.in, with completely overhauled administrative and database back-ends, in under 3 months.
An example of a simple but powerful new feature that we developed after we made the switch to RoR is our customized newsletter. Rails’ ActionMailer makes sending HTML-based emails, something we’d always had difficulty with in PHP, a snap. Just create a template using HTML, the same way you’d create a view for a web page, and Rails handles the headers automatically so that the email is rendered properly as HTML by the recipient’s mail client. ActionMailer also makes it easy to embed the plain-text fallback alternative for mail clients that don’t like HTML. Our geospatial database and PostGIS allow us to use geoblurring to show information relevant to each user’s specific neighborhood in the newsletter when possible, and include popular stories from nearby major metropolitan areas as well. In PHP, we would have had to: wrangle with the PEAR::Mail library for our HTML email, write custom functions for determining adjacent neighborhoods in the system, and we would have had no way to test successful email delivery. In comparison, in Rails we got the email and spatial capabilities for free, and we were able to deploy the fully-featured newsletter functionality, including full unit testing coverage and an administrative interface to preview emails, in just a week!
I compared our old PHP repository to the Ruby one and here’s what I found:
|Old PHP version||New RoR version|
|Total commits to svn: 3,702 in 12 months||Total commits to svn: 1,515 in 3 months|
|Total physical lines of source code*: 58,061||Total physical lines of source code*: 11,401|
By switching to Rails we were able to shrink our maintained codebase to just 20% of its former size while expanding the overall feature-set of the system. There have been some learning curve-related hiccups over the past few months as we acclimated to a new system, but on the whole we now have a leaner, better codebase, more control over our system, and are developing in a language and framework that are joys to code in. We’re very happy with the switch so far.
* Measured using David A. Wheeler’s SLOCCount. Code not written by us (such as the Rails framework and any plugins we’re using, in addition to the unit tests we’ve written) is not included in these counts. Physical lines of source code is kind of a superficial measure, admittedly, and sloccount doesn’t appear to parse our rhtml or haml views, so there are probably some missing lines of code in the Ruby count, but because we’ve adhered pretty strictly to MVC this time around, most of the code that’s missing in this count is just presentation-level control structures.