Saturday, January 27, 2007

Ruby: Invoking a method with a ampersand-parameter

On a few ocassions recently I've been asked what the & does when it is used in the context of a method invocation parameter. For example, consider the following code, specifically line 6 where collect is called.
1. # traditional
2. [1,2,3].collect { |number| number % 2 } #=> [1,0,1]
3.
4. # collect with a previously created block
5. block = lambda { |number| number % 2 }
6. [1,2,3].collect &block #=> [1,0,1]
It's fairly easy to see what is going on from the above example; however, more often I run into code that looks like the following code.
def clone_collect(&block)
clones = collect { |item| item.dup }
clones.collect &block
end
The previous example shows a method that clones each item and then passes on the block to the collect method of the clones array. The above code seems to be a tripping point, I assume it's because the block is defined outside the method definition.

Using a ¶meter with a method invocation is explained very well within PickAxe:
Invoking a Method
[ receiver. ] name [ parameters ] [ block ] 
parameters: ( [ param, ... ] [ , hashlist ] [ *array ] [ &a_proc ] )
block: { blockbody }
do blockbody end
...

A block may be associated with a method call using either a literal block (which must start on the same source line as the last line of the method call) or a parameter containing a reference to a Proc or Method object prefixed with an ampersand character.
Another good explanation can also be found in PickAxe:
If the last argument to a method is preceded by an ampersand, Ruby assumes that it is a Proc object. It removes it from the parameter list, converts the Proc object into a block, and associates it with the method.
An understanding of the above is crucial if you want to comprehend how the following code works within a Rails codebase.
area_codes = phone_numbers.collect &:area_code
Reducing the following statement you can see that area_codes is being set equal to the result of collect being called on phone_numbers. The phone_numbers variable is an array of PhoneNumber instances. The PhoneNumber class has an area_code attribute.

So, the only mystery is what does &:area_code do? As previously stated, if the last parameter is prefixed with an &, ruby removes it from the parameter list, and converts the Proc object into a block. The conversion from a parameter into a block is done through the to_proc method of the parameter. Therefore, by defining the to_proc method it is possible to alter the behavior of any parameter passed to a method that expects a block.
class Greeter
def to_proc
lambda { "hello world" }
end
end

def greet
yield
end

greet &Greeter.new #=> "hello world"
Applying this idea to the String class you could define to_proc as below and create blocks using strings and eval.
class String
def to_proc
text = self
lambda { eval text }
end
end

instance_eval &"2 + 2" #=> 4
Along the same lines, Rails defines the Symbol.to_proc method to create a new proc which takes args. The first element of args is expected to be the item from the collection. The item from the collection is sent the symbol (self from the code below) which is the symbol that specifies which attribute to return. The full code can be seen below.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
The result is a proc that allows you to iterate the collection and return an array of the attribute that is specified by the symbol (:area_code in our example).

The following code should be fully executable and show the concept in entirety.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end

PhoneNumber = Struct.new :area_code
*phone_numbers = PhoneNumber.new(904), PhoneNumber.new(646), PhoneNumber.new(616)
area_codes = phone_numbers.collect &:area_code #=> [904, 646, 616]

Class Reopening Hints

In my previous entry about Class Definitions Aman King left the following comment:
I've always liked Ruby's open class feature but have also wondered how do you keep track of all the changes made to the class definition during runtime? ...
There isn't an easy way (that I know of) out of the box to know what files made what changes to your objects. But, are a few things that you can do that may give you hints as to where behavior is coming from.

Use modules instead of adding behavior directly.
On my current project we needed to add a % method to symbol. You can accomplish this with the following code.
class Symbol
def %(arg)
...
end
end
The above code does what you need, but leaves no hint that you've made a change to Symbol. An alternative solution is to define a module and include that module in Symbol.
module SymbolExtension
def %(arg)
...
end
end

Symbol.send :include, SymbolExtension
Granted, this isn't a huge hint, but if you check Symbol.ancestors you'll find the following list.
Symbol
SymbolExtension
Object
Kernel
Many people believe this is better than nothing, but the choice is yours.

Use the stack trace.
Another option is to use the stack trace to try to track down a specific method. If you are working with some code where a method is being modified somewhere, but it isn't in a module the following code could help you out.
class Symbol
def self.method_added(method)
raise caller.to_s if method == :%
end
end

class Symbol
def %(arg)
self
end
end
The above code uses the method_added hook method and raises and exception when the method you are looking for is defined. At this point the stack trace should show you where the method was defined.

Use conventions.
In practice I've had very little trouble with finding where behavior is defined. In all the projects I've been involved with we have a few conventions that we follow that help ensure we can find behavior definitions easily.
  • Define behavior for the class PhoneNumber (for example) in the phone_number.rb file
  • If you need to open a class that you have not created, create a [Class]Extension module and include it as shown above.
  • Avoid dynamically adding behavior in unexpected places when possible. For example we don't define behavior in associations, such as:
    # not recommended
    has_many :people do
    def by_name
    find(:all)
    end
    end
As I previously stated, I'm on a 14 person team currently. Those 14 people create quite a few features at a rapid pace. Despite our size and rapid pace, I can't remember ever having trouble finding behavior.

Friday, January 26, 2007

Class Definitions

One of the things that makes Ruby very interesting to me is the ability to do things that I previously could not do in C#. For example, Ruby has open classes so I can define behavior of a class in various places.

In this post I'll need a term to describe code written in Ruby that could be written in the same way using Java or C#. Since I worked primarily with C# before Ruby I'll use R#.

I'll start with a fairly easy example where I have a class that has some class and instance methods and some of the class methods need to be protected.
# R# version
class Navigator
class << self
def standard_navigator
self.new standard_path
end

def promo_navigator
self.new promotion_path
end

protected
def standard_path
[:index, :account_creation, :terms_of_service, :check_out]
end

def promotion_path
[:promo_landing, :account_creation, :check_out]
end
end

def initialize(path)
@path = path
@current = 0
end

def next
@current += 1
@path[@current]
end
end
The above example is a fairly standard implementation that puts the class methods at the top, public above the protected, and then the instance methods below. A possible problem with the above code is that if you don't have the class << self code visible when viewing the file (because you've scrolled down) it is not immediately obvious that the methods are class methods. You could argue that the using the class << self is the problem; however, it's the only clean way I've found that allows you to define protected class methods.

An alternative way to define the class can be found below.
class Navigator
def initialize(path)
@path = path
@current = 0
end

def next
@current += 1
@path[@current]
end
end

class << Navigator
def standard_navigator
self.new standard_path
end

def promo_navigator
self.new promotion_path
end

protected
def standard_path
[:index, :account_creation, :terms_of_service, :check_out]
end

def promotion_path
[:promo_landing, :account_creation, :check_out]
end
end
Is this actually better? I'm not sure, but I'd be willing to try it out.

Here's another example. I want a class that has three attributes (properties in C#), is able to initialize these properties in the constructor or default them, and contains some behavior.
# R# version
class PhoneNumber
attr_accessor :area_code, :exchange, :station

def initialize(area_code=nil, exchange=nil, station=nil)
@area_code, @exchange, @station = area_code, exchange, station
end

def formatted_number
"(#{area_code}) #{exchange} #{station}"
end
end
The above code is easy enough to read, but Ruby already has a class that encapsulates the attribute and constructor initialization pattern: Struct. The above code can also be written like below.
PhoneNumber = Struct.new :area_code, :exchange, :station

class PhoneNumber
def formatted_number
"(#{area_code}) #{exchange} #{station}"
end
end
Less readable? Perhaps, but is it if you know what behavior Struct.new encapsulates?

Here's another example in the context of a test.
# R# version
class ValidatableTest < Test::Unit::TestCase
class StubClass
include Validatable
attr_accessor :name
validates_presence_of :name
end

test "when a name is empty, then the instance is invalid" do
assert_equal false, StubClass.new.valid?
end
end
While the above code works, it begins to break down when you need multiple stub classes. You can use names such as StubClass2, StubClass3 or look for more descriptive names but when you are testing similar but slightly different situations it can be very hard to come up with good names. It is also less desirable to have the class defined outside the scope of the test that uses the class.

An alternative solution allows you to use an unnamed class within the test that needs it.
class ValidatableTest < Test::Unit::TestCase
test "when a name is empty, then the instance is invalid" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_presence_of :name
end
assert_equal false, klass.new.valid?
end
end
The above test is very explicit about what behavior can be expected from the class under test. The above test also ensures that if the test fails you wont need to go elsewhere to see any set up code. This example is the one where I have an opinion, and I much prefer the 2nd version.

Ruby allows you to add behavior to classes in many ways. Using a combination of the various ways we may be able to find more descriptive class definitions, or prove that the traditional ways are superior.

Saturday, January 20, 2007

Adding Validations to any Class

On my current project we have data that needs to be collected and then sent to a service. This data needs to be validated, but since it is never put into a model it cannot be validated by using ActiveRecord's validations. To handle this scenario we designed something similar to the module below that can add validations to any class that includes it, which are generally Presenters on my project.
module Validatable
module ClassMethods
def validates_format_of(*args)
validate_all(args) do |attribute, options|
self.validations << ValidatesFormatOf.new(attribute, options[:with], options[:message] || "is invalid")
end
end

def validates_presence_of(*args)
validate_all(args) do |attribute, options|
self.validations << ValidatesPresenceOf.new(attribute, options[:message] || "can't be empty")
end
end

def validate_all(args, &block)
options = args.last.is_a?(Hash) ? args.pop : {}
args.each do |attribute|
yield attribute, options
end
end
protected :validate_all

def validations
@validations ||= []
end

def validate(instance)
self.validations.each do |validation|
instance.errors.add(validation.attribute, validation.message) unless validation.valid?(instance)
end
instance.errors.empty?
end
end

def self.included(klass)
klass.extend Validatable::ClassMethods
end

def valid?
errors.clear
self.class.validate(self)
end

def errors
@errors ||= Validatable::Errors.new
end
end
As you can see I only included the code to expose the validates_presence_of and validates_format_of validations. We actually have quite a bit more, but I think those two are all that's necessary to follow the example. I like the way we designed the validation classes because they can easily be tested and are all treated the same way when it comes time to verify if they are valid or not (the validate method). The code below shows all that is necessary for both the ValidatesPresenceOf and ValidatesFormatOf classes.
module Validatable
class ValidationBase
attr_accessor :message
def initialize(message)
self.message = message
end
end

class ValidatesPresenceOf < ValidationBase
attr_accessor :attribute
def initialize(attribute, message)
self.attribute = attribute
super message
end

def valid?(instance)
(!instance.send(self.attribute).nil? && instance.send(self.attribute).strip.length != 0)
end

end

class ValidatesFormatOf < ValidationBase
attr_accessor :attribute, :regex, :message
def initialize(attribute, regex, message)
self.attribute = attribute
self.regex = regex
super message
end

def valid?(instance)
instance.send(self.attribute) =~ self.regex
end
end
end
The only other piece to the puzzle is the errors collection. The code for this is also very straightforward.
module Validatable
class Errors
extend Forwardable

def_delegators :@errors, :empty?, :clear

def on(attribute)
@errors[attribute.to_sym]
end

def add(attribute, message)
@errors[attribute.to_sym] = message
end

def initialize
@errors = {}
end
end
end
Another important thing to note is that these validations integrate directly with the ActionView::Helpers::ActiveRecordHelper.error_message_on method. This means the same code in the view that displays ActiveRecord errors can also display errors from any object that includes Validatable.
<%= error_message_on :presenter, :name %>
And, here's a few tests if you want to ensure that it works as expected.
class ValidatableTest < Test::Unit::TestCase
test "given no presence when object is validated then valid returns false" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_presence_of :name
end

assert_equal false, klass.new.valid?
end

test "given no presence when object is validated then it contains errors" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_presence_of :name
end
instance = klass.new
instance.valid?
assert_equal "can't be empty", instance.errors.on(:name)
end

test "given invalid format when object is validated then valid returns false" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_format_of :name, :with=>/.+/
end

assert_equal false, klass.new.valid?
end

test "given invalid format when object is validated then it contain errors" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_format_of :name, :with=>/.+/
end
instance = klass.new
instance.valid?
assert_equal "is invalid", instance.errors.on(:name)
end

test "given valid data after it is previously invalid when object is validated then it is valid" do
klass = Class.new
klass.class_eval do
include Validatable
attr_accessor :name
validates_format_of :name, :with=>/.+/
end
instance = klass.new
assert_equal false, instance.valid?
instance.name = "Jay"
assert_equal true, instance.valid?
end
end

Wednesday, January 17, 2007

Appending to ERB output from a block declaration

I've recently been writing up some material and using ERB to handle the majority of my formatting needs. For example, the code below shows what my template may start with.
<%= title "Appending to ERB output" %>
I use ERB to generate both .doc and .html files. If I generate an html file the above template will produce the html found below.
<title>Appending to ERB output</title>
This is very straightforward stuff easily handled by ERB. I use classes and bindings for my needs, but the example below is a simplified version that should get the point across.
require 'erb'

template = <<eos
<%= title "Appending to ERB output" %>
eos

def title(text)
"<title>#{text}</title>"
end

puts ERB.new(template).result
I recently ran into a different situation that took a bit more effort. In the material I was writing up I needed a sidebar. I thought that the best way to represent the sidebar in my template was to use a block. Using a block ensures that the sidebar, when generating html, will be properly closed by requiring an "end".
<%= title "Appending to ERB output" %>

<% sidebar do %>
sidebar content
<% end %>
Adding the content from the sidebar to the output is easily achieved by calling "yield".
require 'erb'

template = <<eos
<%= title "Appending to ERB output" %>

<% sidebar do %>
sidebar content
<% end %>
eos

def sidebar
yield
end

def title(text)
"<title>#{text}</title>"
end

puts ERB.new(template).result
However, the above implementation hasn't appended any tags to mark the beginning or end of the sidebar. Based on the way that the title method works you might assume that the following would work.
require 'erb'

template = <<eos
<%= title "Appending to ERB output" %>

<% sidebar do %>
sidebar content
<% end %>
eos

def sidebar
"<div border=1>#{yield}</div>"
end

def title(text)
"<title>#{text}</title>"
end
But, the above code does not produce any div tags. This is because <%= .. %> mark ruby expressions that are replaced with the result of the expression, and we used <% .. %> which is used to evaluate ruby code but not append.

A way to solve this issue is to tell ERB where to store the output. ERB allows you to specify, as a constructor argument, a variable to store the output in. This allows you to append to the output from within a block declaration.
require 'erb'

template = <<eos
<%= title "Appending to ERB output" %>

<% sidebar do %>
sidebar content
<% end %>
eos

def sidebar
@output << "<div border=1>"
yield
@output << "</div>"
end

def title(text)
"<title>#{text}</title>"
end

ERB.new(template, nil, nil, "@output").result

puts @output
The above code produces the following result.
  <title>Appending to ERB output</title>

<div border=1>
sidebar content
</div>

Sunday, January 14, 2007

Another Rails Presenter Example

Jamis Buck recently posted an entry about Moving associated creations to the model. His solution is cool and probably sufficient for the needs of most; however, if you don't fall into that group you may be interested in an alternative solution using a Presenter.

In the example the view contains fields that collect person, email, and phone number information. Jamis shows what the html would actually look like, but I'm going to show what I would put in the view (rhtml) for my example.
<% form_for :presenter do |form| %>
...
<%= form.text_field :name %>
...
<%= form.text_field :email %>
...
<%= form.text_field :phone %>
<% end %>
Given the above view, the controller could contain the following code.
def create
@person = UsersPresenter.new(params[:presenter]).create_person(current_account)
redirect_to person_url(@person)
end
Using a Presenter limits the responsibilities of the controller without requiring that the model take on those responsibilities. For our example we'll assume the same Person class that Jamis already defined, except ours only needs the associations defined.
class Person < ActiveRecord::Base
has_one :email_address
has_one :phone_number
end
Finally, the Presenter brings all of this together.
class UsersPresenter
attr_accessor :name, :email, :phone

def create_person(account)
person = account.people.create(:name => name)
person.create_email_address(:address => email) unless email.nil?
person.create_phone_number(:number => phone) unless phone.nil?
end

def initialize(hash={})
hash.each_pair { |key, value| self.send :"#{key}=", value }
end
end
While the UsersPresenter class is fairly straightforward it does require the effort to create the additional class. I don't believe that it is worth the trouble for strictly academic reasons (e.g. a separation of concerns debate). However, I do believe that the resulting presenter class may be more easily testable. For example, testing the presenter can be done using a mocking framework such as Mocha.
class UsersPresnterTest < Test::Unit::TestCase
test "a person is successfully initialized from create_person" do
account=mock
account.expects(:people).returns(people=mock)
people.expects(:create).with(:name => "Jay").returns(person=mock)
person.expects(:create_email_address).with(:address => "j@j.com")
person.expects(:create_phone_number).with(:number => "2125551212")
presenter = UsersPresenter.new(:name => "Jay", :email => "j@j.com", :phone => "2125551212")
presenter.create_person(account)
end
end
Using Jamis' (admittedly simpler) solution would require saving data to the database and verifying it's existence.

Using Presenters has additional advantages such as their ability to easily integrate with ActiveRecord validations, separation of view behavior from models (such as formatting a phone number), and allowing you to put validation error messages somewhere other than in a model. I'll address each of these scenarios in upcoming blog entries.

Thursday, January 11, 2007

Ruby: Refactoring - a First Example

Chapter 1. Refactoring, a First Example

How do I begin to write about refactoring? The traditional way to begin talking about something is to outline the history, broad principles, and the like. When someone does that at a conference, I get slightly sleepy. My mind starts wandering with a low-priority background process that polls the speaker until he or she gives an example. The examples wake me up because it is with examples that I can see what is going on. With principles it is too easy to make generalizations, too hard to figure out how to apply things. An example helps make things clear.

So I'm going to start this book with an example of refactoring. During the process I'll tell you a lot about how refactoring works and give you a sense of the process of refactoring. I can then provide the usual principles-style introduction.

With an introductory example, however, I run into a big problem. If I pick a large program, describing it and how it is refactored is too complicated for any reader to work through. (I tried and even a slightly complicated example runs to more than a hundred pages.) However, if I pick a program that is small enough to be comprehensible, refactoring does not look like it is worthwhile.

Thus I'm in the classic bind of anyone who wants to describe techniques that are useful for real-world programs. Frankly it is not worth the effort to do the refactoring that I'm going to show you on a small program like the one I'm going to use. But if the code I'm showing you is part of a larger system, then the refactoring soon becomes important. So I have to ask you to look at this and imagine it in the context of a much larger system.

The Starting Point

The sample program is very simple. It is a program to calculate and print a statement of a customer's charges at a video store. The program is told which movies a customer rented and for how long. It then calculates the charges, which depend on how long the movie is rented, and identifies the type movie. There are three kinds of movies: regular, children's, and new releases. In addition to calculating charges, the statement also computes frequent renter points, which vary depending on whether the film is a new release.

Several classes represent various video elements. Here's a class diagram to show them (Figure 1.1).

I'll show the code for each of these classes in turn.
Movie

Movie is just a simple data class.

class Movie
  CHILDRENS = 2
  REGULAR = 0
  NEW_RELEASE = 1

  attr_reader :title
  attr_accessor :price_code

  def initialize(title, price_code)
    @title, @price_code = title, price_code
  end
end


Figure 1.1. Class diagram of the starting-point classes. Only the most important features are shown. The notation is Unified Modeling Language UML [Fowler, UML].



Rental

The rental class represents a customer renting a movie.

class Rental
  attr_reader :movie, :days_rented

  def initialize(movie, days_rented)
    @movie, @days_rented = movie, days_rented
  end
end


Customer

The customer class represents the customer of the store. Like the other classes it has data and accessors:

class Customer
  attr_reader :name

  def initialize(name)
    @name = name
    @rentals = []
  end

  def add_rental(arg)
    @rentals << arg
  end

  def statement
    total_amount, frequent_renter_points = 0, 0
    result = "Rental Record for #{@name}\n"
    @rentals.each do |element|
      this_amount = 0

      # determine amounts for each line
      case element.movie.price_code
      when Movie::REGULAR
        this_amount += 2
        this_amount += (element.days_rented - 2) * 1.5 if element.days_rented > 2
      when Movie::NEW_RELEASE
        this_amount += element.days_rented * 3
      when Movie::CHILDRENS
        this_amount += 1.5
        this_amount += (element.days_rented - 3) * 1.5 if element.days_rented > 3
      end

      # add frequent renter points
      frequent_renter_points += 1
      # add bonus for a two day new release rental
      frequent_renter_points += 1 if element.movie.price_code == Movie.NEW_RELEASE && element.days_rented > 1

      # show figures for this rental
      result += "\t" + element.movie.title + "\t" + this_amount.to_s + "\n"
      total_amount += this_amount
    end
    # add footer lines
    result += "Amount owed is #{total_amount.to_s}\n"
    result += "You earned #{frequent_renter_points.to_s} frequent renter points"
    result
  end
end


Customer also has the method that produces a statement. Figure 1.2 shows the interactions for this method. The body for this method is on the facing page.

Figure 1.2. Interactions for the statement method



Comments on the Starting Program

What are your impressions about the design of this program? I would describe it as not well designed and certainly not object oriented. For a simple program like this, that does not really matter. There's nothing wrong with a quick and dirty simple program. But if this is a representative fragment of a more complex system, then I have some real problems with this program. That long statement routine in the Customer class does far too much. Many of the things that it does should really be done by the other classes.

Even so the program works. Is this not just an aesthetic judgment, a dislike of ugly code? It is until we want to change the system. The compiler doesn't care whether the code is ugly or clean. But when we change the system, there is a human involved, and humans do care. A poorly designed system is hard to change. Hard because it is hard to figure out where the changes are needed. If it is hard to figure out what to change, there is a strong chance that the programmer will make a mistake and introduce bugs.

In this case we have a change that the users would like to make. First they want a statement printed in HTML so that the statement can be Web enabled and fully buzzword compliant. Consider the impact this change would have. As you look at the code you can see that it is impossible to reuse any of the behavior of the current statement method for an HTML statement. Your only recourse is to write a whole new method that duplicates much of the behavior of statement. Now, of course, this is not too onerous. You can just copy the statement method and make whatever changes you need.

But what happens when the charging rules change? You have to fix both statement and html_statement and ensure the fixes are consistent. The problem with copying and pasting code comes when you have to change it later. If you are writing a program that you don't expect to change, then cut and paste is fine. If the program is long lived and likely to change, then cut and paste is a menace.

This brings me to a second change. The users want to make changes to the way they classify movies, but they haven't yet decided on the change they are going to make. They have a number of changes in mind. These changes will affect both the way renters are charged for movies and the way that frequent renter points are calculated. As an experienced developer you are sure that whatever scheme users come up with, the only guarantee you're going to have is that they will change it again within six months.

The statement method is where the changes have to be made to deal with changes in classification and charging rules. If, however, we copy the statement to an HTML statement, we need to ensure that any changes are completely consistent. Furthermore, as the rules grow in complexity it's going to be harder to figure out where to make the changes and harder to make them without making a mistake.

You may be tempted to make the fewest possible changes to the program; after all, it works fine. Remember the old engineering adage: "if it ain't broke, don't fix it." The program may not be broken, but it does hurt. It is making your life more difficult because you find it hard to make the changes your users want. This is where refactoring comes in.

Tip

When you find you have to add a feature to a program, and the program's code is not structured in a convenient way to add the feature, first refactor the program to make it easy to add the feature, then add the feature.

Ruby: Refactoring, Ruby Edition

A few of my colleagues and I have decided to write, with Martin's permission, a Ruby version of Refactoring.

To begin with this will be a port of the existing Refactoring text. After we finish the port, we are going to look at Ruby specific refactorings. As I go through porting the text I'm going to post what I work on to my blog.

Wednesday, January 03, 2007

Rails: Enterprise Ready

"Is Rails Enterprise Ready?"

I've avoided the question since I started working with Rails. In fact, if pressed, I previously would have stated that Rails wasn't enterprise ready. Claiming that it isn't ready is much easier than proving that it is.

But, now things are different. I'm working on a development team with 14 coders. Our application has it's own database and also integrates with 2 other legacy databases. Our application also integrates with external services via SOAP and RESTful web services. The application currently has a unit test suite that consistently runs in less than 1 second. It also has a domain model that is separated from the UI by inserting a Presenter layer.

Did Rails handle this type of environment out of the box? No. However, Ruby + Rails made it easy to extend Rails where it was necessary. Since I was able to easily extend the framework to my needs, I'm now completely comfortable stating that Rails is "Enterprise Ready". In fact, out of the box Rails solves about 80% of the problems I have, which is better than most "Enterprise" software I'm usually working with.

Out of the box, Rails expects you to be working with one database that you have full control over. Sometimes, life isn't that easy. Luckily, back in January of 2006 Dave Thomas wrote a blog entry on how to create and share database connections to additional databases. Using this article as a reference, we were able to fairly easily integrate our application with our database and the 2 legacy databases we needed to both read and write to.

Connecting to external services was also an easy task. We wrote a few Gateways that took advantage of Net::Http. These Gateway classes took our domain objects, mapped them to valid request objects for the external services, and formatted the result to our needs.

We've spent a lot of time ensuring that our test suite is quite solid, yet ran as fast as possible. The first step was removing access to the database from the unit tests. After that, we also looked at allowing ActiveRecord::Base subclasses to be tested without needing access to the database. The result is a sub 1-second unit test run that provides greater than 80% code coverage.

We also spent a fair amount of time on creating Presenter classes that sit between the UI and the Models. In our application several of the pages contain more than one domain model. For example, a page may collect a billing address and credit card information. Instead of creating several models in the controller we create one presenter instance that collects and validates input. The presenter instances also contain methods that can create model objects from the validated user input. The result is a clean domain model and an easily unit testable presentation layer.

Above are, in my opinion, the significant changes we made to mold Rails to our needs on this project. There were a few other changes we made that were not as major but also contributed to the success we've had so far. For example, we stopped using migrations because of some pain we were feeling due to our team size. Instead, we drop and recreate our database with every build using ActiveRecord::Schema.define, a tip we picked up from Dave Thomas. We also automated our check in process to ensure everyone follows the same steps before checking in. This has lead us to very few broken builds.

Rails is great for building web applications. For building enterprise web applications, Rails is often good enough. And, for building complicated enterprise web applications, Rails is easily extendable. Because of this, Rails is Enterprise Ready.