Rails 3.0 shipped in 2010 and the Merb merge was a success. Today Rails is at version 8.x, having integrated everything envisioned here (modularity, stable APIs, engines as first-class citizens) and much more. Lighthouse is gone, therubymine.com no longer exists, and many links in this article are dead — but the core ideas still hold.
Almost every web developer knows or has at least heard of Ruby on Rails, a full-stack framework for building web applications using the Ruby programming language.
If you’ve never heard of Rails or web applications, there’s a brief overview on Wikipedia, where it’s impossible not to be struck by its Philosophy. Rails is defined by its author David Heinemeier Hansson as “opinionated software” — software that imposes certain approaches and workflows during the design and development of a project, with all the advantages and disadvantages that entails.
Another characteristic that marked the early evolution of Rails (2003-2007) was the lack of robust interfaces for extending it through external plug-ins, partly enabled by a controversial Ruby feature: monkeypatching. In Ruby, classes are never closed: you can modify their behavior at any point in the program, and this applies to core classes too (e.g. String, Integer, …). This led to a proliferation of plug-ins and framework extensions that relied on private implementation details whose stability over time was never guaranteed, with all the maintainability problems that follow: anyone who followed the early Rails releases cannot forget the lengthy debate that arose from the implementation of Rails Engines.
Later, engines were rehabilitated, even being presented at the 2009 edition of RailsConf as a viable path for building reusable, complete software components — since they include Models, Views, Controllers, and Routes that connect the URIs an application responds to with the code implementing its logic.
This change of vision on DHH’s part was driven by his experience of having to reimplement several applications that could have been encapsulated in an engine and subsequently reused.
Similar considerations were also expressed regarding Rails’ strong opinionated character, whose imposed approaches don’t just concern the use of a certain pattern, but also the imposition of a specific “piece of software” implementing it. For example, to access a database in Rails you use ActiveRecord, an implementation of the Object-Relational Mapping pattern that bridges the relational model of currently widespread databases with the object oriented model used by Ruby and pervasively inherited by Rails.
The Open Source context¶
In an open source context, however, such a restriction is seen as stifling by many developers. While ActiveRecord does its job well, it’s important to be able to choose the component best suited to a given purpose: it’s a concept that any experienced developer embraces, setting aside pointless religious wars :).
Modularity, extensibility, and the presence of a well-designed and above all stable interface are the founding principles of Merb, another Ruby-based framework for building database-backed web applications, whose tagline is “Looking for a hacker framework?”. Merb consists of a small, well-organized core of functionality, on top of which a series of plug-ins build and realize the complete scaffolding on which you then develop your application.
With Merb you can use your preferred ORM, template engine, mailer, and testing frameworks, since they all rely on the same core. Moreover, it’s straightforward to build new ones to satisfy the most disparate needs: it’s a philosophy very similar to the UNIX one, where each individual software tool implements limited functionality (but does it well), and solving more complex problems requires chaining different tools together.
Given the numerous advantages of this approach — completely opposite to Rails’ initial one — even a Rated R individual with strong opinions decided to change his mind once again, and announce to the world the news nobody expected: Rails and Merb would become a single project!
The result of this merge would materialize in the next major release of Rails, version 3.0, which was the subject of a substantial talk at RailsConf 2009, and whose features would be:
Less “opinionated”: no longer a single “Rails Way” but multiple “Rails Ways”, given the ability to choose between different ORMs (AR, Sequel, DataMapper, CouchRest, …), templating engines (ERb, HAML, Liquid, Markaby, …), Javascript libraries (Prototype, jQuery, MooTools, Dojo, …) and testing frameworks (Test::Unit, RSpec, Mocha, …).
Faster: the Merb development team was always attentive to performance, striving to avoid writing software with too much “magic” (e.g. abuse of method_missing) and to follow its philosophy of modularity and confining a component to a single application domain. Rails 3 would inherit these design approaches, ensuring better performance. In this vein, Metal was introduced in Rails 2.3.
A public API: you learn by making mistakes. If it’s true that you can’t predict how an end user will use software, the ways a developer can use a framework are equally multiple and unpredictable — and they become evil if they’re not provided with an API and guidelines for extension. The long debate around Rails Engines made history, and there was no point in repeating the same mistakes.
More modular and more agnostic, direct consequences of introducing an API, enabling the creation of “composable” applications — the framework being not a single tower, but rather a set of tools a-la Lego Technic (fond memories :). A feature confirming this approach, already available in Rails 2.3, was Rails templates: they offered a DSL for automating the initialization of a new application, by writing requirements in a .rb file to be passed as an argument to the -m parameter of the rails command. This blog post by lifo contains everything you need for a quickstart.
More evolvable: a direct consequence of greater modularity and a change of vision. In Rails 3 there would be no more “Sacred Cows” — any aspect of the framework could be subject to change. Don’t be alarmed: as long as the API remains stable and there’s a defined deprecation process for APIs marked as obsolete, developers would have no headaches. There were far more headaches in the past due to the absence of an API, where everyone implemented the features they needed however they saw fit.
Live from the stage¶
One (of the very many) examples of how this grand merge was being carried out can be seen directly on GitHub — specifically, two commits on ActionController. It was completely restructured, and the new implementation was placed in a new directory, new_base. In the first commit, Rails2Compatibility was introduced and the fixture templates were removed.
Subsequently, in the second commit, the switch from the old ActionController::Base to the new one took place, also inserting some temporary hacks to keep the tests passing.
Following a merge of this magnitude carried out by established professionals is an excellent exercise, especially for those who have recently entered software engineering and want to learn firsthand the best practices that lead big rewrites to success.
The future?¶
Rails 3 would be a remarkable leap forward in the history of this framework, leaving behind the most controversial parts of its philosophy and enabling the community to evolve it in ways previously impossible. It’s advisable for every developer to follow its development, since there’s also much to learn about project management processes and approaches, beyond software development itself. The Rails project management with its milestones was handled through Lighthouse, while all the source code was hosted on GitHub. Given the nature of git (and GitHub), anyone can, at any time, fork Rails and modify it as they please. It’s a possibility that few other platforms for open source software development offer.
Additionally, you could follow the Rails Core Team on Twitter, stay updated on high-level developments by following Ryan Daigle’s blog, follow discussions around Rails 3 through the mail-to-web gateway on ruby-forum.com and, of course, bookmark therubymine.com since we’d be talking about Rails 3 again soon on these pages :).
See you soon!
Note: This article was originally published on therubymine.com, an Italian collective blog about Ruby and Rails that no longer exists. I’m republishing it here to preserve it.