Forum: Ruby on Rails alias_method_chain vs. redefined method with super

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.
Cad4ee2e7b6c756c9c4a58bfbc1986b8?d=identicon&s=25 Dustin Frazier (Guest)
on 2006-12-26 19:50
I'm trying to fully understand the subtleties of using
alias_method_chain to refine method behavior versus redefining a method
and calling super.  I have a simple data model (a music collection) that
I often use to evaluate web frameworks, and I'm trying to get it working
on Rails 1.2.0RC1.

Specifically, I have three classes which subclass a common Artist class:
- Band (name:string)
- Musician (first_name:string, last_name:string)
- Duo (first_artist:Artist, other_artist:Artist)

I'm using single table inheritance to store all of the fields for the
various Artist types in one table.  I want the 'name' attribute to be
derived for Musicians (first_name+last_name) and Duos
(first_artist.name+last_artist.name) and persisted so I can sort all
Artists by name.

I added code to Musician which redefined first_name= as:

class Musician < Artist
  def first_name= (first_name)
    super(first_name)
    update_name # sets name to first + last
  end
  ...
end

For the Duo class, however, this didn't work.  It's definition looks
like:

class Duo < Artist
  belongs_to :first_artist, :class_name => 'Artist'
  belongs_to :other_artist, :class_name => 'Artist'
  ...
end

When I tried to define first_artist= and call super as I did for
Musician, it complained that the method didn't exist in super.  I dug
around a bit and discovered alias_method_chain, so I finally ended up
with:

class Duo < Artist
  belongs_to :first_artist, :class_name => 'Artist'
  belongs_to :other_artist, :class_name => 'Artist'
  def first_artist_with_update= (first_artist)
    self.first_artist_without_update = first_artist
    update_name # sets name to first_artist.name + other_artist.name
  end
  alias_method_chain :first_artist=, :update
  ...
end

Thinking that was a pretty cool way to extend a method, I went back and
tried to use the same scheme for Musician, but there I get the missing
method error again!  Strange, since there's definitely a first_name=
method, although it's defined on Artist not Musician.

So, I guess I have two questions:

1. Why couldn't I call super within Duo.first_artist=, when :belongs_to
is supposed to have added a method by that name?  Is it because the
additional methods are defined directly on Duo (and thus not really
super-able)?

2. Why can't I use alias_method_chain in my Musician class?  Does
alias_method_chain only work for methods defined directly on the current
class?

Having to do this two different ways depending on where the method in
question is defined seems a bit messy.  I'm hoping there's a single
scheme I've missed that will work in both cases.

Thanks, and sorry for the long post...

Dustin
This topic is locked and can not be replied to.