Thursday, December 4, 2008

Extend Your ActiveRecord Association Methods

Much of the beauty of ActiveRecord associations is in the collection methods that are provided for you when you define has_many relationships.

For instance, when we say:
class Organization < ActiveRecord::Base
has_many :people
end

We now have an organization.people method that returns the collection of associated people within the organization. Easy enough. We also get nice little methods on the collection of people like organization.people<<, organization.people.build, organization.people.create and organization.people.find (among others). Well what if you wanted to define your own method on this auto-magically provided collection method? You do this through Association Extensions which let you define methods to add to the collection. You can define an association extension either with a block or a module – we’ll use a block provided to the has_many call here as it’s the most common way to do so:

class Organization < ActiveRecord::Base
has_many :people do
def find_active
find(:all, :conditions => ["active = ?", true])
end
end
end

I’ve defined a find_active method which will retrieve all people in the organization that have the active column set to true. This can be invoked very intuitively with:

organization.people.find_active

This is a great way to provide convenience finder methods for common retrievals on the associated collection.

If you want to define an extension as a module just provide the :extend option in your has_many definition:
module FindActiveExtension
def find_active
find(:all, :conditions => ["active = ?", true])
end
end

class Organization < ActiveRecord::Base
has_many :people, :extend => FindActiveExtension
end
You can customize to your heart’s content – these are just some simplistic examples of how to plug into this nifty feature.

No comments: