Forum: Ruby on Rails Overwriting / Decorating ActiveRecord association accessor

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Marcel H. (Guest)
on 2008-11-19 20:54
(Received via mailing list)
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
Frederick C. (Guest)
on 2008-11-19 21:21
(Received via mailing list)
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
Marcel H. (Guest)
on 2008-11-20 14:23
(Received via mailing list)
>
> 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 :) Thumbs up!

Marcel
Marcel H. (Guest)
on 2008-11-20 14:38
(Received via mailing list)
I was a bit too fast and euphoric :)
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
This topic is locked and can not be replied to.