A Post Entitled RSpec best practices
A few days ago Philippe Creux posted his RSpec Best Practices and Tips. The post is well worth reading even if you prefer another test framework (you are testing, right?!) because there are several tips that are applicable to TDD more broadly than rspec alone. Of all the tips there are two that I cannot re-emphasize strongly enough: “Only One Expectation Per It Block” and “(Over)Use Describe and Context”.
Single Expectation Tests
The “one expectation” tip is more broadly expressed as “each test should make only one assertion.” Philippe’s example is a good one: rather than have one test that asserts that all expected attributes are present, have multiple tests that assert that individual attributes are present. The advantage of this approach lies in its granularity. The “one expectation” way allows to you to more quickly identify when multiple expectations have been violated. Why? Because a monolithic test will fail on the first failed expectation even though there may be multiple points of failure behind it.
The impetus for a monolithic test is typically the perceived advantage of collecting all the similar expectations into one place. Grouping the expectations does make it simpler to determine where to alter or extend that type of testing. Taking Philippe’s example, if you wanted to replace ‘age’ in the list of attributes with ‘dob’ (date of birth) and add ‘shirt_size’ then you would know right where to go to do that type of thing. For this reason I would make one additional recommendation that I’ve mentioned in the past: use the dynamic nature of ruby to your advantage by using code to create expectations. For example, rather than the recommended syntax
it { should respond_to :name }
it { should respond_to :age }
it { should respond_to :gender }
Try the following
[:name, :age, :gender].each do |expected_attribute|
it { should respond_to expected_attribute }
end
This code retains the advantages of both co-locating similar kinds of tests and employing discrete “one expectation” tests. Personally I believe it is also more expressive of the intention of the test, all the more when you build blocks for required_attribute or nonnegative_attributes.
Context is King
The “(Over)Use Context” tip is spot on. Early on in my use of rspec I tended to have code littered with one-off tests. That is, most of the test code was duplicated except for one or two key parameters. By using contexts, specifically nested contexts, you can reduce the duplication and bring sharper focus to what is varying. Use the outer context to group all those unchanging parameters and let the outer context description identify how they are common. Then, use the nested context to explicitly declare what is varying. Importantly, the before block in each context should set up the test scenario as described by the context.
As an additional example, consider a class with a state machine. The state machine begins in the ‘pending’ state and then moves to the ‘active’ state only when the ‘activate’ event is triggered. You might begin testing this scenario as follows.
describe Thing do
before :each do
@valid_attributes = { ... }
end
it "should create an instance given valid attributes" do
lambda{ Thing.create @valid_attributes}.should change(Thing, :count).by(1)
end
it "should default to the pending state upon creation" do
@thing = Thing.create @valid_attributes
@thing.should be_pending
end
context "pending instance" do
before :each do
@thing = Thing.create @valid_attributes
end
it "should transition to 'active' when activated" do
lambda{ @thing.activate }.should change(@thing, :state).to('active')
end
end
end
From the flow of the code we can see just what was described: if the attributes are valid we can create a new instance and that instance will correctly default to the pending state and from the pending state we can activate the instance and it will become active. Perfect. Until. Until? Yes, until you have to modify the state machine. Let’s say you’ve run with this code for a while and found a bot probing your application. To filter out bot created things you decide to begin with an ‘unconfirmed’ state that requires an email confirmation of some type.
What happens with the tests in this new case? The second test (default to pending) naturally fails. So does the third test (transition to active). Should it? Probably not.
What’s missing is that the before block did not guarantee that the testing state was what the context claimed that it was. How do you guarantee such things? Add an assertion. This step is commonly overlooked in a lot of tests that I have seen.
context "pending instance" do
before :each do
@thing = Thing.create @valid_attributes
@thing.should be_pending
end
it "should transition to 'active' when activated" do
lambda{ @thing.activate }.should change(@thing, :state).to('active')
end
end
The only change here is the addition of the assertion to the before block. When you re-run the tests, the third test about transitioning to ‘active’ will still fail. However, now the failure will indicate that the error lies with the assertion in the before block. Previously we had assumed the object was in the ‘pending’ state because it was the default state. Now we make that assumption explicit and the test report will quickly help us understand that the failure was in the test setup rather than in the state machine implementation.
Personal Preference
I don’t personally care for the shortcuts Philippe recommends. I don’t think that the use of ‘specify’ is quite as expressive as the typical it-block that invokes it in most rspec code. This matters to me somewhat because I still hold onto that thin hope that a non-technical person might be able to read an rspec and ‘get it.’ Using the more standard ‘it-block’ style also allows me to grep my rspecs for expectations. The other shortcut — using braces rather than do/end syntax for declaring tests — does not seem practical to me. In practice, only the most trivial tests are written in one line (or maybe I need more deeply nested contexts).
More Cowbell!
As a final thought, I don’t think that the
lambda{...}.should change(object, :attribute_name)
syntax is used nearly enough. I have a preference, for example, to know that calling ‘create’ actually creates a new instance rather than fails to throw an exception. That’s why in the code snippet above the first test checks to see if invoking create has changed the Thing count by one.
I have not seen the use of change() used as often with instances but it works just as well. In the third test above we’re using it to validate that the state has changed to ‘active’. You need to be careful with this; change() will fail your code if the final value is correct (ie., ended in ‘active’) but you did not change (ie., started in ‘active’ and stayed in ‘active’).
Loading...
A Post Entitled Conditionally absolute
I like footers, well, that appear at the foot of the page. I guess that seems obvious enough but what I really mean is a bit more specific. If I have a ‘short’ page in which the page content only extends halfway down the bottom of the browser window (viewport) then I want the footer pushed to the bottom of the viewport. If I have a ‘long’ page where the content scrolls past the bottom of the viewport then the footer should just appear at the end of the content.
I could probably wait for the footer tag coming in HTML 5. I do not know, however, if rendering engines will widely adopt my wishes for footer placement. Moreover, I don’t particularly care to wait for widespread implementation of HTML5 across browsers, particularly those ‘non-modern’ browsers that are likely to dominate my user base. I need the answer now.
Absolute positioning
Absolute positioning would seem to be a great answer. But it’s not. I tried the following (haml/sass):
#footer{:style=>'position: absolute; bottom: 0;'}
This solution worked very well for the ‘short’ page on which I first tested it and I was actually pretty happy with it. The page renders with blank space between the end of the content and the nearly-black 3em footer. The problem is that it had the exact opposite effect of not positioning the footer absolutely. Specifically, with long pages I now have the footer stuck in the middle of the content (rather than in the middle of a short page with blank space trailing the footer). Back to the drawing board.
Conditional absolutes
Really I had the two pieces that I needed in place. For long pages I could let the footer stay in place at the end of the content. For short pages I could force it to the bottom of the viewport. If only I could switch between the two…
Which of course I could, with jquery. Actually it took jquery and an additional class on the footer div. The styling for the additional class contains the style that I was applying inline above. Specifically: (sass)
#footer.floor
:position absolute
:bottom 0
Having created that simple class I then added the following jquery snippet to my $(document).ready function:
if ( $(window).height() > $('body').height() ) {
$('#footer').addClass('floor');
} else {
$('#footer').removeClass('floor');
}
This code simply compares the height of the ‘body’ (the content) to the height of the viewport. If the content is shorter than the viewport then we add the ‘floor’ class to the footer, adding the absolute positioning to the bottom of the viewport for ‘short’ pages. If the content is longer than the viewport then we remove the ‘floor’ class (just in case it had been added previously) and let the footer sit at the end of the content.
A Post Entitled I am the Keymaster, are you the Gatekeeper?

Several weeks ago I started writing an authorization gem on the way home from a weeks’ vacation. The problem with the set of gems and plugins that I’d used in the past were several. One gem was much too tightly coupled to an authentication gem that I no longer used. Others required too much wiring. So, off I went to create the next great gem. At least until I got home and ran into a stray question in a ruby forum about the DeclarativeAuthorization gem.
DeclarativeAuthorization is the gem that I wished I’d written for a number of reasons. First, DeclarativeAuthorization is almost entirely self-contained from the rest of your application. It’s only requirement is that your user/account model support a collection of role_names. How you support that collection is entirely up to you. That’s the kind of separation that I really wanted and that ultimately had triggered my ideas for writing a gem in the first place.
DeclarativeAuthorization uses a ruby script to define roles and to assign privileges to those roles. The approach is simple and clean… even when the rules for roles get murky. There are two big advantages to this. One is that the rules do not depend on any “Rails magic” or golden values in your database. The other is that the roles and privileges can grow with your project regardless of the eventual complexity.
Composing Privileges
Out of the box DeclarativeAuthorization has a simple set of privilges for CRUD… conveniently named Create, Read, Update, and Delete. The privileges are declared as follows.
privileges do
privilege :manage, :includes => [:create, :read, :update, :delete]
privilege :read, :includes => [:index, :show]
privilege :create, :includes => :new
privilege :update, :includes => :edit
privilege :delete, :includes => :destroy
end
What’s been really well thought out here is how privileges should be composed together. For example, it seems fairly obvious at the UI level that in order to be able to ‘update’ something you must first be able to ‘edit’ it (at least in the Rails view of REST). Similarly, DeclarativeAuth sensibly defines ‘read’ as ‘show’ and ‘index’.
But what if you wanted to go a level higher? For example, what if you have an admin area and you know that only admins should be able to perform any CRUD? Won’t it get annoying repeating tests for each aspect of CRUD? Nope. Because you can compose the privileges. That’s the essence of the first line of the block. In that line we have a “manage” privilege that is defined to be the same as granting each individual C/R/U/D privilege.
Roles Compose, Too!
DeclarativeAuth also supports composing roles as well.
authorization do
role :guest do
has_permission_on :conferences, :to => :read do
if_attribute :published => true
end
has_permission_on :talks, :to => :read do
if_permitted_to :read, :conference
end
has_permission_on :users, :to => :create
has_permission_on :authorization_rules, :to => :read
has_permission_on :authorization_usages, :to => :read
end
role :user do
includes :guest
has_permission_on :conference_attendees, :to => :create, :join_by => :and do
if_attribute :user => is {user}
if_permitted_to :read, :conference
end
has_permission_on :conference_attendees, :to => :delete do
if_attribute :user => is {user}
end
has_permission_on :talk_attendees, :to => :create do
if_attribute :talk => { :conference => { :attendees => contains {user} }},
:user => is {user}
end
has_permission_on :talk_attendees, :to => :delete do
if_attribute :user => is {user}
end
end
...
end
Obviously there’s a *lot* going on in that code snippet. The point here is found in the first line of the block for ‘role :user do’ — ‘include :guest’. Simply put, the user gets to do everything that a guest can do plus what’s defined in the rest of the block. That makes for a very powerful and concise way to keep track of roles and privileges.
Without getting into the details too much, the other thing to note in the definition of the :user role is the if_attribute calls. if_attribute allows the role definition to move beyond global scope for the class and validate privileges on an instance by instance basis. The if_attribute calls in the :user definition essentially say “if the current user is the user associated with the instance (the one that created it) then the user can…”.
Integration across the Rails MVC stack
With the ability to set privileges based on attributes of a particular instance you may be thinking, “Wow, I could use that to secure data at the instance level…” You’d be right. And, of course, DeclarativeAuth already does that.
DeclarativeAuth has a simple API that allows you to specify privileges in the models to secure access at the (data) class level in addition to the broader access control at the controller level. There are even nice helpers available in the views to show/hide UI based on the privileges of the current user.
ConferenceAttendee data class
class ConferenceAttendee < ActiveRecord::Base
using_access_control
belongs_to :user
belongs_to :conference
validates_presence_of :user, :conference
validates_associated :user, :conference
end
ConferencesController#index
def index
# Only show conferences that the current user may read:
@conferences = Conference.with_permissions_to(:read)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @conferences }
end
end
Note: All the code snippets presented here come from the sample app for DeclarativeAuthorization
A Post Entitled Time to clean your filters
The Problem
What do you do when your end user needs to filter? In some cases the answer is easy: provide a custom method for the sort criteria. For example, when you know that your end user wants to know “my jobs” as distinct from “all jobs” a custom ‘mine’ method might work just fine. Don’t worry that the custom routes are not RESTful; they are, they are just not the default Rails notion of REST. That’s okay; Rails is not necessarily right.
The filtering that I run into is rarely that simple. Right or wrong end users tend to think more options is better. In the context of filtering that means they often want to filter by a combination of ad-hoc attribute values. Clearly a single custom method won’t work there because you can’t out guess the combination and permutations that a given user might want to use.
Sorting and paging further complicate the issue. Even when you can pick the ‘right’ values the user may want them back in the ‘right’ order. Paging is just a small wrinkle on top of that but yet another piece to layer in.
The Context
The most frequent context for the type of filtering/sorting/paging that I’m talking about is when the user is presented with a list of things that needs to be pared down and organized before the user can make any sense out of it. Maybe they’re looking at a list of members in a club or a set of subscriptions or a bunch of invoices. Whatever the case, you’ve given them a set of things to review in the order you thought best but it doesn’t make sense to them. Rather than haggle over who’s right (you… of course!), you decide to give them a filtering pane and some click-to-sort headers in the grid. Great. The UI is done. But where does it all go? Where do you send the values?
More often than not, this context leads me right back to where it started. You began presenting the user a list that naturally flowed through the #index action of your controller. Why should the filtered or sorted or paged list be any different? It’s still just a list, isn’t it?
The Solution
In my mind the answer to that question is yes. A filtered list is still just a list so if the original list came from the index action of my controller then the filtered version of it should come that way, too.
The way that I’ve settled on implementing most of these scenarios lately is through a combination of named scopes, anonymous scopes, and some recommendations from Uncle Bob’s Clean Code.
Scopes
Named scopes and anonymous scopes are hardly new territory. Named scopes came into Rails at version 2.1 courtesy of a very popular plugin. The idea behind named scopes, if you’re not familiar with them, is that you create a method that ‘scopes’ a query against your ActiveRecord-based model. This is really handy if you have a scope like ‘current’ or ‘active’ that you can use over and over in your application; you just declare it once on the class and use it wherever you need it.
class Order < ActiveRecord::Base
named_scope :recent, {:limit=>10, :order=>'id DESC'}
named_scope :since, lambda{|date| {:conditions=>['created_at > ?', date]}}
end
Order.recent
#=> [...up to 10 orders]
Order.since(1.month.ago)
#=> [... all orders created in the last month ...]
Just as a quick refresher in case you’re not using named scopes (as you should be!), you create a named scope on a class by calling the named_scope method in the class definition. The first parameter to the method is the name of the ‘scope’ and the second argument is either a hash of find options or a lambda that returns a hash of find options.
Anonymous scopes are pretty much the same thing. Really, the only difference is that named scopes are not saved against the model. You create them only where you need them and let the Garbage Collector have them when you are done with them.
Order.scoped( {:limit=>10, :order=>'id DESC'} )
#=> same results as Order.recent
What makes named and anonymous scopes so useful for the type of ad hoc filtering and sorting that we’re considering is that you can chain them. By chaining named and anonymous scope calls you build up the query conditions. Thus you do not have to worry too much about the what combination of filering, sorting, and paging the user might want, you simply accumulate them. The query is not actually run against the database until you first try to use the data.
Order.recent.since(1.week.ago)
#=> Up to ten orders from the last week
Clean code
So what does clean code have to do with this? In the third chapter of his 2009 book by the same name, Bob Martin makes an excellent case for code that’s organized into a series of very tiny, top-down methods. This, again, is not really new territory for most developers. Martin just pushes it to an end that I’d not really considered before and the discussion of the top-down organization somehow clicked with me in a way that it had not before.
The clean code approach to the filtering/sorting/paging problem would look at the demonstration in Ryan Bates’ Railscast* and say it’s too big. The filtering should be refactored into it’s own method, so that the index can focus solely on getting the right type of view to render out the values. That filtering method should be broken down into a series of smaller methods, each of which performs one specific type of filtering/sorting/paging.
class ProductsController < ApplicationController
def index
filter_products
sort_products
respond_to do |format|
format.html # render index.html.erb
format.xml { render :xml=>@products.to_xml }
end
end
private
def filter_products
initialize_scope
filter_by_name
filter_by_category
filter_by_price
end
def initialize_scope
@products = Product.scoped {}
end
def filter_by_name
return if params[:name].blank?
@products = @products.scoped :conditions=>[ 'name LIKE ?', "#{params[:name]}%" ]
end
def filter_by_price
filter_by_minimum_price unless params[:minimum_price].blank?
filter_by_maximum_price unless params[:maximum_price].blank?
end
def filter_by_minimum_price
return if params[:minimum_price].blank?
@products = @products.scoped :conditions=>['price < ?', params[:minimum_price]]
end
def filter_by_maximum_price
return if params[:maximum_price].blank?
@products = @products.scoped :conditions=>['price < ?', params[:maxiumum_price]]
end
def filter_by_category
return if params[:category_id].blank?
@products = @products.scoped, :conditions=>{:category_id=>params[:category_id]}
end
end
Conclusion
Okay, so nothing too earth-shattering if you’ve been deep into Rails for a while but hopefully a help if you’re a relative novice. Have we gained anything? Sure, we’ve gained a few things. The use of named and anonymous scopes has greatly simplified our ability to respond to the user who desires to do ad hoc filtering against our data. They also make sorting and paging relatively simple — just add an appropriate scope that users :order, :limit, and :offset appropriately and you can sort or page any of the target result sets the user could dream up. Just as importantly the top-down organization of very tiny (generally private) methods makes the top-most levels of the program (the index and initial filter method) read somewhat like a newspaper article: the headline (index) describes the main event, the first paragraph (#filter) provides the most important details, and the subsequent ‘paragraphs’ (lower methods in the chain) progressively reveal the implementation details. We have a simple solution to a problem with many combinations that should be easy to read and maintain in the future.
A side benefit
This approach saved me a lot of work earlier today. I had a rather inelegant solution to a particular problem in which I needed to filter and sort a list of members. The twist was that I needed the exact same sorting and filtering for two completely different contexts with very different views representing the results. The initial approach was to send the filtering request to the #index method of the MembersController; it seemed like a natural place to organize the member-specific logic. The method chose the view for rendering the results based on the ‘commit’ value (the name of the submit button). Unfortunately, a certain “non-modern browser” was not supplying the commit value. Ugh!
How did we keep it DRY? Simple. Since the code was organized with this top-down approach I simply extracted the methods from the controller class into a module and included the module in the two controllers that needed the search logic. The big benefit was that I only needed to move the lower-level functions; the higher functions (e.g., #index) remained in place. Actually the #index method was simplified since it could now focus on rendering the list of Members in only one way; the other controller picked up the single call to filter and rendered the results as it needed to. Simple code, simple refactoring, DRY solution.
Anyone have a glass of water?
* No offense intended to Ryan or his Railscast, which was focused on the mechanics of using anonymous scopes and immensely helpful in helping me get a handle on how to use them.
A Post Entitled STI Factory revisited
Single Table Inheritance (STI) Revisited
I wrote about Single Table Inheritance (STI) in Rails several months ago. STI is a simple design pattern in which multiple subclasses are stored in a single database table and distinguished by a discriminator column. Rails makes this easy to implement by automatically mapping a column named ‘type’ as the discriminator column (aka, inheritance_column). Of course you can override the name of the discriminator column and I often must do so in practice; most of the applications of STI that I use allow the end-user to select the value for the subclass and trying to render the list of subclasses for the :type column leads to rendering issues.
Allowing the end user to select the subclass has one other problem — your controller must somehow be aware of the use of STI. Why? Well, ActiveRecord::Base simply does not allow you to assign a value to the inheritance column. It keeps things “type safe” by setting the value of the inheritance column itself. As a result your controller needs to have some sort of STI-awareness built in so that the user can send back a value for the inheritance_column and the controller can use that value for building or creating an instance of that type.
Instant STI Awareness
This need for STI-awareness is prevalent enough that I offered an attempt at creating it in a lib/plugin in the earlier post. The solution focuses on the model, rather than the controller, so that the controller can remain blissfully unaware (some would say decoupled from) the implementation of the model. Unfortunately that earlier code stunk and I’ve been revisiting it as a part of getting ready for my talk at the South Carolina Ruby Conference.
One of the weak points of the earlier code was the shaky way it tried to work around infinite loops. That was what brought me back to the code. I was looking for a good example of alias_method_chain and realized that it was the solution to the recursion problem.
The basic logic behind the plugin/lib is simple. We need to override the #new method to:
- Check for the presence of the inheritance column in the attributes supplied to the new method.
- If the inheritance column is found, check to see if the its value is the name of a valid subclass.
- If a valid subclass has been requested then call new on the subclass and pass the original args less the inheritance_column.
- If a valid subclass was not requested then call new on the superclass.
alias_method_chain
Phrasing the problem in the right way is often the key to unlocking the problem. As steps 3 and 4 above suggest we really want to have a way to hide the inherited #new function, override its functionality, and then invoke that original method. That’s what alias_method_chain is all about.
alias_method_chain is an extension of Module added by Rails. The intention of the method is to allow you to wrap an existing method with your new functionality. For example, assume that you have a method called foo that you want to extend by some functionality known as bar. You can think of the original method as “foo without bar” and the new functionality as “foo with bar”. For the sake of the other developers with whom you work (think: the world!) you would want to use some aliasing so that others could make use of your fabulous new bar-ology without having to change their code. It would probably look something like this:
alias_method :foo_without_bar, :foo
alias_method :foo, :foo_with_bar
And that is exactly what alias_method_chain does, only with a much simpler syntax:
alias_method_chain :foo, :bar
Placement of alias_method_chain calls is very important. The call must be made after both your new “foo with bar” concept has been added to the class and the original “foo” has been realized. This can get tricky when you are trying to wrap class-level functionality.
Improved STI Factory
Here’s a revised version of the STI factory code. The recursion problem is gone thanks to alias_method_chain and, as a side benefit, STI tables get a new subclass_names method that can be used for building select options.
module Koinonia
module StiFactory
def self.included(base)
base.extend Koinonia::StiFactory::ClassMethods
end
module ClassMethods
def has_sti_factory
extend Koinonia::StiFactory::StiClassMethods
class << self
alias_method_chain :new, :factory unless method_defined?(:new_without_factor)
end
end
end
module StiClassMethods
def subclass_names
subclasses.map(&:name).push(self.name)
end
def new_with_factory(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
klass_name = options.delete(self.inheritance_column.to_sym) || self.name
klass = self.subclass_names.include?(klass_name) ? klass_name.constantize : self
klass.new_without_factory(*args.push(options))
end
end
end
end
Just to explain what’s going on a little bit… when Koinonia::StiFactory is included into ARec::Base by init.rb it adds a class-level method to ARec::Base called ‘has_sti_factory’. That method is the one that you’d add to an STI class to hook in the factory. When invoked, that method extends the class by adding two methods: new_with_factory that is responsible for checking the supplied attributes and invoking the appropriate new_without_factory, and subclass_names that supplies the names of the known subclasses. With that in place you can now do this:
class Vehicle < ActiveRecord::Base
self.inheritance_column = 'vehicle_type'
has_sti_factory
end
class Car < Vehicle; end
class Truck < Vehicle; end
class MonsterTruck < Truck; end
Vehicle.new
=> #<Vehicle id: nil, vehicle_type: nil, ...>
Vehicle.new :vehicle_type => 'Truck'
=> <Truck id: nil, vehicle_type: 'Truck', ...>
Vehicle.new :vehicle_type => 'MonsterTruck'
=> #<MonsterTruck id: nil, vehicle_type: 'MonsterTruck', ...>
Oh, yeah, I’ve tried to play nice with all the cool kids and wrapped this up as a plugin that you can download from github.
A Post Entitled New in Rails 2.1: Timestamped migrations
What was wrong with migrations?
If you’ve been part of any development team that was larger than the “Army of One” you’ve probably run into an issue with migrations. It’s happened to me a few times: one member of the teams goes head-down on some problem and it takes longer than expected. Not wanting to check in ‘broken” code the patch builds up for a while… and so do the migrations to fix db issues. Finally ready, the change gets checked in and … poof… What worked no longer works. Why?
While Mr. Fix-It was head down the trunk was updated with other migrations. But these migrations had overlapping numbers so when they merged into the code base it was unpredictable which ones would be run on any given system. To be clear, the migrations will be run in a very definitie order. They’re run in alphanumeric order, but only one migration of a specific ‘version’ will be executed. As a result, which migrations are run on your system depends on how many you’d already checked out and run and the alphabetical naming of each script. Now it’s up to you and your team to rename all the migrations, backing them out one by one and adding them back to make sure all the database changes are applied appropriately. Yikes!
Enter Sandman
Disclaimer: I’ve only heard ‘Sandman’ when certain closers enter baseball games but I thought someone would appreciate the reference
The new timestamped migrations may put all these issues to rest. Instead of prefixing the migrations with 001, 002, 003, etc the prefix will now be a timestamp. So, the result of running a ‘script/generate scaffod MyObject attribute1:string attribute2:integer’ will be a file with a name like 20080601214508_create_my_object. The likelihood that you and a teammate create a migration at the exact same time is pretty small so the ‘level collisions’ are almost surely a thing of the past.
Tracking revisions, not the version
Even better, though, is that the schema_info table will now track revisions, not only the latest version. That is, every migration that is run via rake db:migrate will be recorded in the database. As a result, whenever Mr. Fix-It decides to enlighten the rest of the team with his update, a rake db:migrate will be able to identify the individual migrations that have not been run whether they were on Mr. Fix-It’s machine (when he finally updates from trunk/master) or on a teammates’ machine (when the patch is loaded).
Even better, there are new rake db:migrate:up and rake db:migrate:down commands. These commands accept an individual migration ‘version’ (the time stamp) and either run it (up) or back it out (down). Remember that table that you created and decided you’d overengineered? Now it’s a lot easier to back that one out.
Could it get even better?
Yes, it could get better. Those of you who’ve read The Rails Way (Obie Fernandez, Addison-Wesley Professional Series, 2007) may have come across a recommendation to accumulate migration changes until they are pushed to production. That is, rather than create three migrations for a table and some additional fields while the table is in development, there is a recommendation to have one create script that gets updated until it’s pushed to production. I’ve tried this on a couple of apps and really liked the approach because it cuts down on the ‘noise’ in the migration collections. I’m willing to accept the argument that migrations are not really necessary for tracking database changes until they change something beyond development.
What could be even better that the current implementation of the timestamped migration would be if it could detect these changes in the migration files. It should be possible to check the creation and update times of the files to see if they’ve been updated and then validate the updated time in the migrations db. This particular idea has some drawbacks, particularly if a production migration were ever touched accidentally.
A Post Entitled 5 Tips for ActiveResource
The first couple of tips have an indrect impact on ActiveResource. Still, they are worth keeping in mind because they simplify the data with which ActiveResource deals.
Tip 1: Use delegate and :method for encapsulation
If your crash course in Ruby involved reading the Agile book, then the delegate method may be new to you. Delegate is a class-level command that allows you to pass certain method calls on to an associated model. For example, if you have a highly-factored address book you might have a pair of models like this:
class Address < ActiveRecord::Base
belongs_to :zip_code
end
class ZipCode < ActiveRecord::Base
has_many :addresses
end
That’s a model with some theoretical purity… but in practice it’s cumbersome. You really want to deal with an address that has all the information you’d like to render (street, city, state, zip) in on model. Atleast it should feel that way. That’s precisely where the delegate command comes into play.
class Address < ActiveRecord::Base
belongs_to :zip_code
delegate :city, :state, :zip, :to=>:zip_code
delegate 'city=', 'state=', 'zip=', :to=>:zip_code
end
Modeled as shown above you can ask an address for it’s city and the address will pass the request on to the zip_code object to which it belongs, retrieve the answer, and return it to you. (It’s taking advantage of the fact that Rails is doing some method_missing magic to provide getters and setters for your attributes). That level of encapsulation will become increasingly important when you begin to use ActiveResource heavily. In many cases you may want to return only a few fields from an associated model and, as in the example above, you do not want or need to reveal how you’ve organized your data to the outside world.
The final piece to the puzzle with respect to ActiveResource will be making sure you use the :method parameter when you serialize the delegating object to xml.
addresses_controler.rb
...
def show
@address = Address.find(params[:id], :include=>:zip_code)
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @address.to_xml(:methods=>[:city, :state, :zip])
end
end
...
As shown, the call to @address.to_xml tries to include the results of calling the city, state, and zip getter methods on address. The delegate command causes the Address object to pass that request on to the association ZipCode object and the results are returned and placed into the xml envelope as if they were attributes of the address (which they are, indirectly). The application that’s consuming all this through ActiveResource remains blissfully unaware of your modeling nirvana. It simply receives some nicely formatted xml along the lines of this:
<home-address>
<id type="integer">1</id>
<street>123 Main St.</street>
<city>Anytown</city>
<state>XX</state>
<zip>12345</zip>
</home-address>
Tip 2: Clean up the delgation you just learned to keep the code clean and clear
If you start maximizing your use of delegate your code can get untidy especially since delegate introduces some duplication when you’re dealing with attribute accessors. If we keep in mind that class declarations are still Ruby scripts then we can clean the attribute accessor delegation pretty easily while making the intent very clear.
class Address < ActiveRecord::Base
belongs_to :zip_code
[:city, :state, :zip].each do |delegated_accessor|
delegate "#{delegated_accessor}", "#{delegated_accessor}=", :to=>:zip_code
end
end
On to some tips with more direct bearing on ActiveResource itself.
Tip 3: Use AppConfig to get your site information out of the class file!
The Core did a great job modeling ActiceResource along the lines of ActiveRecord so that using ActiveResource feels very natural to any Rails programmer. But it’s also left me stumped as to why there is no equivalent to /config/databases.yml. I suppose that in some cases you will be using a well-known, established, public REST interface but I’m finding ActiveResource to be a very natural way to develop ‘sub-applications’ that can be shared to create a larger application. Because of that I need to be able to have different site information for development, test, and production. Clearly some configuration is needed.
Even though I shudder at the thoughts that a name like ‘AppConfig’ brings to mind, it’s a great part of the solution to this problem. If you’re not familiar with it, AppConfig allows you to provide a yaml config files for global (/config/app_config.yml) and environment-specific (e.g., /config/environments/development.yml) configuration. The plugin reads these config files, merges inforamtion as necessary, and provides all the options as class-level attributes of the AppConfig class.
sites:
addressbook: http://localhost:3001
financials:
url: http://localhost:3002
username: money
password: talks
The yaml above shows two different types of configuration that would be useful for ActiveResource, organized together under a ‘sites’ attribute. The first one (addressbook) is the way I started before I ran into an application that needed http basic authentication. The site info consists only of the url. The second one (financials) came out of the latter need. A quick extension of ActiveResource causes these to spring into action.
class ActiveResource::Base
protected
def self.establish_site_connection(site_id)
raise(ArgumentError, "#{site_id} is not defined for #{RAILS_ENV}") unless AppConfig.sites.respond_to?(site_id)
site_info = AppConfig.sites.send(site_id)
return site_info.respond_to?(:url) ? site_with_basic_auth_info(site_info) : site_info
end
def self.site_with_basic_auth_info(site_info)
site = URI.parse(site_info.url)
site.userinfo = "#{site_info.username}:#{site_info.password}"
return site.to_s
end
end
I’ve been dropping the code above into /lib/core_ext/active_resource_extension.rb. The first method (establish_site_connection) is meant to emulate ActiveRecord::Base#establish_database_connection. It accepts a site id in the form of a symbol or string and retrieves the site configuration matching that id. If that site info is already a simple string, that string is returned unmodified. If the site_info is further broken down into the url, user name and password for http basic authentication then that is handed off to the site_with_basic_auth_info method to build up a simple string.
It’s true that the http basic authentication credentials could be written into the url. In fact, that’s exactly what the site_with_basic_auth_info does. If that’s the case, then why add the username and password to the config file?
Tip 4: Share your site AppConfig settings between your applications
When you have the fortunate advantage of controlling both your ActiveResource-based application and your ActiveRecord-based application you can share the configuration information between the applications. Specifically, you can share the username and password information used for http basic authentication so that both sides can be externally configured… and reconfigured. By sharing the configuration files and including the use of AppConfig in the source application for the ActiveResource your http basic authentication will be as simple as
def basically_authenticated(user, password)
user==AppConfig.sites.financials.username && password==AppConfig.sites.financials.password
end
What makes this even more compelling is that AppConfig (as anything leaning on yaml) allows you to use ERb in your configuration files. Why is that significant?
Tip 5: Use Embedded Ruby in your configuration files to automatically change your user/password
Clearly with http basic authentication you will want to go the extra step of passing through a secure connection, but if you’re too tired to add an ‘s’ to your http, then you’ll want to change your clear-text password. Often. Embedding Ruby might be just the trick because you could share a single algorithm between your applications that would change the password for you.
sites:
addressbook: http://localhost:3001
financials:
url: http://localhost:3002
username: <%= %w{money cash penny moulah dineiros pennywise poundfoolish}[Date.today.wday] %>
password: <%= Digest::SHA1.hexdigest("#{Date.today.to_s}---financials") %>
There is a potential pitfall here. With this type of approach — shifting the user/password each day — the application servers will have to be kept in step. A reboot on one machine will require a reboot or restart on the other to make sure the applications share the same username/password since the AppConfig object will be re-loaded when the webserver starts. Pick the scheme that works best for you.
A Post Entitled STI Factory
Single Table Inheritance
One of the abstractions that I really like in Rails is its implementation of Single Table Inheritance (STI). If you’re not familiar with STI, it is a simple design pattern in which you model an inheritance hierarchy in a single database table (Martin Fowler does it more justice here). Since ActiveRecord, Rails’ primary domain modeling base class, is also db-centric the marriage of the two is fairly straight forward: include a column called ‘type’ in your database table and you’re done. Simple.
But type is a real headache
In practice it turns out that it’s not always so simple. In a number of applications that I’ve worked on we like to put the user in the driver’s seat by allowing them to select the subtype they are going to create. For example, assume that we start with a domain modeling different types of vehicles. Without getting into all the attributes that might distinguish the vehicles, the class model might look something like this:
class Vehicle < ActiveRecord::Base
def self.inheritance_column
'vehicle_type' # we'll see why in a bit...
end
end
class Car < Vehicle
end
class Truck < Vehicle
end
What I’d really like to do is give the user a select and let them pick either ‘Car’ or ‘Truck’. That in itself is should not be too difficult. There is one little gotcha: type is a reserved word in Ruby. If you try to use a select or select_tag helper Rails (Ruby) will complain with an error that will probably leave you scratching your head for a while. The simple way to avoid this problem is shown above. You override the class-level inheritance column method and return the name of the column that you will use to discriminate among classes in the inheritance hierarchy. In this case we’re using the column ‘vehicle_type’ to hold the name of the subclass.
Things get trickier when you get back to the controller. It turns out that Rails musters up some righteous indignation about any attempt to change the class. To see what I mean, let’s simulate what you might see back in the VehiclesController if you let the user request a Porche Cayenne…
params = HashWithIndifferentAccess.new(:vehicle=>HashWithIndifferentAccess.new(:vehicle_type=>'Car', :make=>'Porche', :model=>'Cayenne'))
=> {"vehicle"=>{"vehicle_type"=>"Car", "make"=>"Porche", "model"=>"Cayenne"}}
vehicle = Vehicle.new params[:vehicle]
=> #<Vehicle id: nil, name: nil, vehicle_type: nil, created_at: nil, updated_at: nil, make: "Porche", model: "Cayenne">
Already we can see there is a problem. The user sent back a request to build a Car, but what is being assembled is a generic Vehicle. The reasoning is pretty straightforward: you asked for a new Vehicle, not a new Car, so you got a new Vehicle. Perhaps too graciously, Rails assumed that you knew what you were asking for. Unforunately, you don’t — the user knows what is being created but you are clueless. You could try to build a big case statement, but that’s very messy and you have to update it each time you add or remove a class from the hierarchy. It also suffers from the fact that it’s too concrete; you can’t transport your knowledge to any other STI implementation.
An STI Factory Method
This sounds like a classic case for the Factory Method design pattern. One of my favorite design pattern books (Head First Design Patterns) says that this pattern “defines an interface for creating an object, but lets subclasses decide which class to instantiate.” If we translate that to Rubyisms and consider our problem, it sounds like we need a module (interface) that will mix into a class that will help the class pick from among its subclasses when it’s asked for something new.
I’ve taken a stab at this a few times and never liked the results. Most of the time it felt like I was injecting too much code. I also got somewhat inconsistent results from the class-level array I was trying to build to maintain the list of subclasses. Recently I was working on a different problem and stumbled on some information that I’d forgotten from my first dance with Rails. I know that David Black told me that ActiveRecord maintained a protected list of subclasses just for STI, but it was washed away in the grey matter (probably because i read it at the beach… I’m a geek.)
Having been reintroduced to ARec#subclasses again, I’ve worked out an abstract STI factory. I built it as a plugin and the essence of it is in the code that gets mixed into the ActiveRecord base_class in the inheritance hierarchy.
def new(*args)
target_class_name = requested_class_name(args)
return self.base_class.factory(target_class_name, *args) unless self.name === target_class_name
super
end
def factory(requested_class_name, *args)
requested_class_name = base_class unless has_subclass_named?(requested_class_name)
requested_class = requested_class_name.constantize
requested_class.new(*args)
end
def type_options_for_select
subclasses.collect{|subclass| [subclass.name.humanize, subclass.name]}
end
protected
# Returns true if the STI tree includes a subclass with the specified name
def has_subclass_named?(subclass_name)
subclasses.detect{|subclass| subclass.name==subclass_name}
end
def requested_class_name(args)
class_name = self.name
if args.last.is_a?(Hash)
requested_class = args.last.delete(self.inheritance_column.to_sym)
class_name = requested_class unless requested_class.blank? or !has_subclass_named?(requested_class)
end
return class_name
end
We’ll read the code from the bottom up, mostly so that the helper methods make sense when we see them in context.
- requested_class_name
This helper method attempts to determine the name of the subclass that is being requested. Like Rails, it begins with the assumption that you knew what you were asking for (class_name=self.name) and then it searches the parameters it was passed to see if the :inheritance_column was passed. If so, it tries to return the value that was requested. There are two conditions on this: if the class name was blank it assumes that you wanted the class from which you requested something new. If you supplied a value but that value is not a subclass it assumes it was a typo (kinder than assuming you were a fool :-) For both cases it falls back to the class_name of the orignal class; otherwise it overrides with a subclass name. An important thing to note is that the subclass name is deleted from the options passed to the method. This is done to prevent an infinite loop but it means that you’ve got to keep a copy of the returned value. - has_subclass_named?
This helper method checks the list of subclasses for the (base) class and makes sure that the requested class actually exists as a subclass. - type_options_for_select
This is a convenience method for the select/select_tag. It builds an array that can be used as the options source with a human readable name for the class as the text and the class name as the value. - factory
This method requires the name of the subclass. It takes advantage of the fact that Ruby classes are global constants (hence the call to constantize) to get a handle on the requested class and then invokes ‘new’ on it, passing in the parameters it received. - new
This is the part that I like most about the plugin. The first thing that it does is check to see if the class you requested differs from the class that is trying to fill the request. If so, it automatically to the factory method and if not you proceed with the default ‘new’ behavior. The advantage to this is that you never have to know what you’re trying to create and you don’t have to remember to use the facotry method. You can just use new (or create) on this class like every other class… and it will figure out what you meant to do.
With that in place things look a bit different for the VehiclesController.
class Vehicle < ActiveRecord::Base
has_sti_factory
def self.inheritance_column
'vehicle_type'
end
end
...
params = HashWithIndifferentAccess.new(:vehicle=>HashWithIndifferentAccess.new(:vehicle_type=>'Car', :make=>'Porche', :model=>'Cayenne'))
=> {"vehicle"=>{"vehicle_type"=>"Car", "make"=>"Porche", "model"=>"Cayenne"}}
vehicle = Vehicle.new params[:vehicle]
=> #<Car id: nil, name: nil, vehicle_type: "Car", created_at: nil, updated_at: nil, make: "Porche", model: "Cayenne">
Now all I have to do is figure out how to make the VehiclesController fulfill that “create Porche Cayenne” request. :-)