# Overriding AR read/write\_attribute - Overridden write\_attribute Is Never Called

**URL:** <https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045>\
**Category:** Rails\
**Created:** [September 24, 2009, 12:29am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045 "2009-09-24T00:29:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 24, 2009, 12:29am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/1 "2009-09-24T00:29:11Z")

</div>

Could someone explain this?

#config/initializers/ar\_attributes.rb

module ActiveRecord  
module AttributeMethods

```
  alias_method :ar_read_attribute, :read_attribute
  def read_attribute(attr_name)
    p "read_override"
    ar_read_attribute(attr_name)
  end

  alias_method :ar_write_attribute, :write_attribute
  def write_attribute(attr_name, value)
    raise 'You made it!'
  end

```

end  
end

In the Rails console:

> > person.read\_attribute :name

“read\_override”  
=\> “Joe”

> > person.write\_attribute :name, “Bilal”  
> > =\> “Bilal”
> 
> > person.read\_attribute :name

“read\_override”  
=\> “Bilal”

---

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 24, 2009, 9:37am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/2 "2009-09-24T09:37:40Z")

</div>

On Sep 23, 11:27 pm, MaggotChild [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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”

Fred

---

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 25, 2009, 2:41am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/3 "2009-09-25T02:41:42Z")

</div>

On Sep 24, 12:34 am, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> at the time alias\_method was called, for example:  
> “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

---

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 25, 2009, 3:18am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/4 "2009-09-25T03:18:00Z")

</div>

On Sep 24, 5:40 pm, MaggotChild [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 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.

Yes, this is what happens, the alias is performed in a class\_eval  
block giving it presidency over my attempted override in the module.

---

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 25, 2009, 3:05am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/5 "2009-09-25T03:05:42Z")

</div>

Hi –

On Thu, 24 Sep 2009, Frederick C. wrote:

> write\_attribute on AttributeMethods but it is too late - the aliasing  
> that occured in Dirty is pointing at the previous implementation.

This thread seems to be going on both here and in ruby-talk. See my  
most recent answer in ruby-talk; there is, indeed an  
alias\_method\_chain call involving write\_attribute (but not  
read\_attribute) that happens before the initializer is executed.

David

–  
David A. Black, Director  
Ruby Power and Light, LLC ([http://www.rubypal.com](http://www.rubypal.com))  
Ruby/Rails training, consulting, mentoring, code review  
Book: The Well-Grounded Rubyist ([The Well-Grounded Rubyist](http://www.manning.com/black2))

---

<div class="post-metadata">

**Author:** ![MaggotChild](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ea924/32.png) [@MaggotChild](https://www.ruby-forum.com/u/MaggotChild)\
**Post date:** [September 25, 2009, 3:19am UTC](https://www.ruby-forum.com/t/overriding-ar-read-write-attribute-overridden-write-attribute-is-never-called/176045/6 "2009-09-25T03:19:11Z")

</div>

Hi –

On Thu, 24 Sep 2009, MaggotChild wrote:

> > included in ActiveRecord::Base, write\_attribute is aliased &  
> > Â alias\_method :old\_implementation, :to\_be\_aliased
> 
> apposed to including it via a module) -which is possible.
> 
> 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](http://www.rubypal.com))  
Ruby/Rails training, consulting, mentoring, code review  
Book: The Well-Grounded Rubyist ([The Well-Grounded Rubyist](http://www.manning.com/black2))
