Overwriting / Decorating ActiveRecord association accessor


#1

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


#2

On Nov 19, 6:08 pm, Marcel H. removed_email_address@domain.invalid wrote:

end

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


#3

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


#4

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