ActiveRecord Delegation

Posted by dave

Ever wanted to be able to delegate ActiveRecord fields between objects when using belongs_to relationships?

What do I mean? Well, lets say you have a really simple normalised database for storing people and the companies they work for:

People and Companies Tables
class Person < ActiveRecord::Base
  belongs_to :company
end
class Company < ActiveRecord::Base
  has_many :people
end

Lets say you want to write the persons address out in a view, you would obviously have to traverse the relationship and might end up with code like this:

<%= @person.company.address %>

Not a massive hassle, but you also need to check if the person actually belongs to a company before you do that or you will get a NoMethodError complaining that company is nil.

<%= @person.company.address unless @person.company.nil? %>

This can pretty quickly become tiresome and clutter up those clean and tidy views you have been striving towards. Wouldnt it be nice to cut out some verbosity and be able to do this?

<%= @person.address %>

At first delegate looks like the answer but and sure enough it would allow an address method to delegate to company but it still causes problems if company is nil. Also it gets kinda ugly when you want to delegate a whole load of fields as was the case with the app I was working with today.

Enter AR-Delegation

Plug-in time! Wouldn’t it be nice to do something like this?

class Person < ActiveRecord::Base
  belongs_to :company
  has_columns :from => :company, :except => "id" 
end

and get a fully nil safe set of delegated methods out of it so you can just call the fields like they belong to the model doing the delegation.

Hopefully these other examples will be self explanatory as to what this little plug-in can do:

has_columns :from => :source, :except => "id" 
has_columns :from => :source, :only => [ "title", "name" ], :prefix => "src_" 
has_column :col_name, :from => :source, :as => :new_name
has_column :col_name, :from => :source

It does allow fields to be prefixed which might be useful if you are bringing in fields from multiple other models or would just like to prefix the fields.

Source

I have popped it up on RubyForge so to install it would be:

script/plugin install svn://rubyforge.org/var/svn/ar-delegation

I would be really interested to see if anyone else finds this useful, I will be updating it with tests and stuff as and when I have the time but I would really love to hear some feedback on it.

Comments

Leave a response

  1. Dave VerwerApril 12, 2007 @ 09:39 AM

    Found a bug

    Boolean fields transferred up with has_columns do not support the [field]? method, so for example if you bring a bool called “error” up, obj.error? no longer works.