Overwriting / Decorating ActiveRecord association accessor

Hi, I am trying to overwrite the accessor of a has_many association. Basically my class looks like this:

class Person   has_many :emails   has_one :link, :class_name => 'PersonProxy'

  def emails_with_link      link.emails + emails_without_link   end   alias_method_chain :emails, :link end

Now that works fine if I only access the collection like

Person.find(1).emails

=> [#<Email...]

But using any collection specific methods throw a NoMethodError

Person.find(1).emails.build

=> NoMethodError: undefined method `build' for #<Array:0x226c634>

which makes sense, as I return an array...

But how do I return the Association? Or are there any other tricks to implement this decorator for associations?

Cheers Marcel

Hi, I am trying to overwrite the accessor of a has_many association. Basically my class looks like this:

class Person has_many :emails has_one :link, :class_name => 'PersonProxy'

def emails_with_link link.emails + emails_without_link end alias_method_chain :emails, :link end

Now that works fine if I only access the collection like>> Person.find(1).emails

=> [#<Email...]

But using any collection specific methods throw a NoMethodError>> Person.find(1).emails.build

=> NoMethodError: undefined method `build' for #<Array:0x226c634>

which makes sense, as I return an array...

The trick is that link.emails isn't an array - it's an association proxy. I'm not sure what the write thing to do here is. Maybe something like

has_many :emails do   def load_target     super     proxy_target += proxy_owner.link.emails   end end

might do the trick ?

Fred

The trick is that link.emails isn't an array - it's an association proxy. I'm not sure what the write thing to do here is. Maybe something like

Thanks so much for your input. You got me in the right direction:

has_many :emails do     def load_target       super       if !loaded? and proxy_owner.link.respond_to?(:emails)         @target += proxy_owner.link.emails       end       @target     end   end

This works like a charm :slight_smile: Thumbs up!

Marcel

I was a bit too fast and euphoric :slight_smile: Now this works better:

  has_many :emails do     def load_target       super       if not @loaded_link and proxy_owner.link.respond_to?(:emails)         puts "loading link"         @target += proxy_owner.link.emails         @loaded_link = true       end       @target     end     def reset       super       @loaded_link = false     end   end