giovedì 3 settembre 2009

Some ActiveRecord fun

Many of you have already used has_many and belongs_to Active Record relationships. This is really easy to do when you have a single attribute to map; like, in example, an Article with many Comments. You’d write something like

class Article < ActiveRecord::Base
has_many :comments

class Comment < ActiveRecord::Base
belongs_to :article

Combining these declarations with a article_id column in your comments table would allow you to:

  • access all the comments of an article with article.comments

  • access the article a comment belongs to with comment.article

There are situations, however, when things get a little more tricky. Think about this example: you have a Movement object, which identifies a cash flow between two Accounts. You also have an accounts table; so, in your movements table, you would add columns like from_account_id and to_account_id.

How can this be mapped with ActiveRecord? We need to write two belongs_to declaration, this way:

class Movement < ActiveRecord::Base
belongs_to :from_account, :class_name => "Account", :foreign_key => "from_account_id"
belongs_to :to_account, :class_name => "Account", :foreign_key => "to_account_id"

This tells ActiveRecord that the movement class must reference two Account objects. One is accessed with movement.from_account and the other with movement.to_account.

You can do the same thing for your Account class:

class Account < ActiveRecord::Base
has_many :movements_out, :class_name => "Movement", :foreign_key => "from_account_id"
has_many :movements_in, :class_name => "Movement", :foreign_key => "to_account_id"

This way, with account.movements_in, you can get all the cash flows to the account, and with account.movements_out all the cash flows going out of the account.

Plain and simple! :)