Hi --

On Thu, 24 Sep 2009, MaggotChild wrote:

>
>
>
> On Sep 24, 12:34 am, Frederick Cheung <[email protected]>
> wrote:
>> On Sep 23, 11:27 pm, MaggotChild <[email protected]> wrote:
>>
>>> Could someone explain this?
>>
>> At a quick glance it is probably because after AttributeMethods is
>> included in ActiveRecord::Base, write_attribute is aliased &
>> overwridden (eg the change tracking module). You then change
>> write_attribute on AttributeMethods but it is too late - the aliasing
>> that occured in Dirty is pointing at the previous implementation. When
>> you alias a method ruby does keep track of what the aliased method was
>> at the time alias_method was called, for example:
>>
>> class Foo
>>   def to_be_aliased
>>     "implementation 1"
>>   end
>>   alias_method :old_implementation, :to_be_aliased
>> end
>>
>> class Foo
>>   def to_be_aliased
>>      "implementation 2"
>>   end
>> end
>>
>> Foo.new.old_implementation #=> "implementation 1"
>
>
> Hi Fred,
>
> Thanks for your response. I think you're on to something and I'll have
> to take a look a the Dirty module (amongst others). But, even if the
> module was aliasing the original write_attribute, I don't see how this
> would interfere with my redefinition.
>
> write_attribute is at the top of the call stack so I'd think it's
> going to use the most recent definition. Unless some other module
> redefined write_attribute within the scope of active AR::Base (as
> apposed to including it via a module) -which is possible.
>
>
> Using your example, I believe the case is more like the following:
>
> class Foo
>  def to_be_aliased
>    p "implementation 1"
>  end
>  alias_method :old_implementation, :to_be_aliased
> end
>
> class Foo
>  def to_be_aliased
>    p "implementation 2"
>  end
> end
>
> Foo.new.to_be_aliased #implementation 2

It involves alias_method_chain, so it's somewhat like this:

module AR
   module M
     def x; puts "M#x"; end
     def self.included(base)
       base.alias_method_chain(:x, :y)
     end
   end

   class Base
     def x_with_y; puts "x_with_y"; end
     p Base.instance_methods(false).sort   # does not include "x"
     include M
     p Base.instance_methods(false).sort   # does include "x"
   end
end

AR::Base.new.x


After alias_method_chain, AR::Base has an "x" method, so overriding
the one in AR::M won't affect what happens when you call x.

I stripped it down to the bare bones (and then some, perhaps :-) but I
think this represents what happens. See the file dirty.rb, which is
where the alias_method_chain call is.


David

-- 
David A. Black, Director
Ruby Power and Light, LLC (http://www.rubypal.com)
Ruby/Rails training, consulting, mentoring, code review
Book: The Well-Grounded Rubyist (http://www.manning.com/black2)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to