A look at ActiveRecord association setters

If you’ve been working in Rails for more than a short while, you should be familiar with ActiveRecord class methods, and how they modify your model definitions with helpful magic methods.

For example, the has_many declaration gives you access to a host of accessors and setters that make it easy to manipulate associated child objects:

Class Family < ActiveRecord
  has_many :members
end

class Member < ActiveRecord
  belongs_to :family
end

# Create a new family and save it
family = Member.new(:name => “The Johnsons”)
family.save

# Add a family member through array insertion
family.members << Member.new(:name => “Sam”)

# Add a family member through association creation
family.members.create(:name => “Sally”)

In the example code above, we created our new family members through the “members” collection. By doing so, the family_id attribute/column is initialized for us. Otherwise, we’d have to set it manually like this:

sunny = Member.create(:name => “Sunny”, :family_id => family.id)

Okay, you might not find that impressive. I mean, we’re only saving a few dozen characters of code here, right?

Turns out there’s another convenient way of building associated objects that I feel doesn’t get enough press. It’s the collection=objects method, which takes an array of associated objects like so:

family.members = [ Member.new(:name => “Jean”), Member.new(:name => “Tom”) ]

You’ll find that for each of these objects the family_id attribute was set, just as they would have been above. As for Sam, Sally and Sunny? They’ve been usurped by Jean and Tom, the once-loyal babysitters. That’s right, in addition to creating new database records for Jean and Tom, the old records are deleted too. That’s a lot of good stuff going on for a single line of code.

Editor’s note—I need to come up with better examples.

It’s also worth mentioning this setter method also works when initializing ActiveRecord objects using a hash. The example code below will create a new family, add a couple family members to it, and save all three objects to the database.

Family.create :name => "The Johnsons", :members => 
  [ Member.new(:name => "Sam"), Member.new(:name => "Sally") ]

Okay, so this isn’t revolutionary, but it’s another solid tool to add to your Rails arsenal if you haven’t already.