# Can't alter (decorate) ActiveRecord::Base#method\_missing

**URL:** <https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544>\
**Category:** Rails\
**Created:** [August 20, 2007, 8:04pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544 "2007-08-20T20:04:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 20, 2007, 8:04pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/1 "2007-08-20T20:04:18Z")

</div>

Hallo – I’m trying to decorate the default behaviour of  
ActiveRecord::Base#method\_missing() with the following code:

`
class ActiveRecord::Base
alias_method( :b023_method_missing, :method_missing ) 
unless method_defined?( :b023_method_missing )
def method_missing( method, args )
puts "\n **** – In method_missing()"
b023_method_missing( method, args )
end
end
`

This, to my thinking, should simply do what ActiveRecord normally does  
with calls to the attributes like “model.name”, etc.  
However, what is happening is that I am getting a “stack level too deep”  
error.  
When run in the console, I get “\*\*\*\*\* – In method\_missing()” printed a  
million times, then the stack overflow error.  
It seems to be that the the call to alias\_method is happening twice  
(despite the unless guard), thus creating an infinite loop.  
Has anyone successfully done something like this with ActiveRecord, and  
if so, could they please tell me how!

Cheers,  
Doug.

---

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 20, 2007, 9:53pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/2 "2007-08-20T21:53:38Z")

</div>

I’m not sure why that doesn’t work, unless the method\_defined? call  
actually hits the original method\_missing.

In any case, is there a reason why you need to use alias\_method instead  
of just overwriting the method in your model class? You can then just  
call super() to hit the original method. It’s what inheritance is there  
for.

---

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 20, 2007, 9:57pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/3 "2007-08-20T21:57:23Z")

</div>

Bryan D. wrote:

> In any case, is there a reason why you need to use alias\_method instead  
> of just overwriting the method in your model class? You can then just  
> call super() to hit the original method. It’s what inheritance is there  
> for.

That’s what I’m looking at now.  
Basically, I want to create a plugin that allows delegation of methods  
to encapsulated models upon the raising of NoMethodError in its own  
method\_missing() method.  
Cheers,  
Doug.

---

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 20, 2007, 10:05pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/4 "2007-08-20T22:05:14Z")

</div>

Then what you probably want to do is define a module that, when  
included, dynamically overwrites the method\_missing method. You’d have  
to do an “include MethodMissingWhackiness” in each class that makes use  
of that functionality.

I’m not sure I understand your use case, though. You want to implement  
subsets of your model’s functionality in separate models that will be  
what, nested classes? And you’d like the parent model to transparently  
delegate those methods? That seems somewhat confusing to me.

Maybe instead, you should consider implementing the subsets of methods  
as modules and just including them into the parent class.

---

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 20, 2007, 10:14pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/5 "2007-08-20T22:14:48Z")

</div>

Bryan D. wrote:

> Then what you probably want to do is define a module that, when  
> included, dynamically overwrites the method\_missing method. You’d have  
> to do an “include MethodMissingWhackiness” in each class that makes use  
> of that functionality.
> 
> I’m not sure I understand your use case, though. You want to implement  
> subsets of your model’s functionality in separate models that will be  
> what, nested classes? And you’d like the parent model to transparently  
> delegate those methods? That seems somewhat confusing to me.
> 
> Maybe instead, you should consider implementing the subsets of methods  
> as modules and just including them into the parent class.

You could be right.  
I think, however, that this could be useful as a simple plugin for those  
situations where you have, say, a Person class that can take on the role  
of Salesman, Customer, Manager, etc.  
There is, in fact, a handy plugin that looks like it might answer this  
at:  
[http://daveverwer.com/2007/3/16/activerecord-delegation](http://daveverwer.com/2007/3/16/activerecord-delegation)

(I’ve just been referred to it by its author on a UK Ruby list.)

> You’d have  
> to do an “include MethodMissingWhackiness” in each class that makes use  
> of that functionality.

Yes – although to make it look more “Railsy”, I’ve reopened  
ActiveRecord::Base and put it in the following method:

def self.delegates\_to( delegatee, options )

# other setup stuff

include MethodMissingWhackiness  
end

& cheers for your input, man!  
Doug.

---

<div class="post-metadata">

**Author:** ![biot023](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7ab992/32.png) [@biot023](https://www.ruby-forum.com/u/biot023)\
**Post date:** [August 21, 2007, 4:21pm UTC](https://www.ruby-forum.com/t/cant-alter-decorate-activerecord-base-method-missing/112544/6 "2007-08-21T16:21:08Z")

</div>

Hi again – just for completeness – I’ve got what I wanted to happen  
working.  
It’s an ongoing thing (so delegated validations are next), but the  
working code so far (after considerable duck-punching) is:

`
require "active_record"
module Biot023
module ActsAsDelegator
```
def method_missing( method, *args )
  begin
    super
  rescue NoMethodError => err
    self.methods.grep( /^_fetch_delegatee_/ ).each do |mname|
      begin
        model = self.method( mname ).call
        raise( "#{ mname } failed to return model in method_missing" 

```
) 
unless model
_method, _args = [model.method( method.to_sym ), *args] 
rescue _method, _args = [ model.method( :method_missing ),
[method, *args] ]
return _args ? _method.call( *_args ) : _method.call
rescue => inner_err
# do nothing
end
end
raise
end
end
end
end
class ActiveRecord::Base
Delegate to a delegatee, whose id must be referenced from this
model, just
the same as a belongs_to() call. In fact, this takes the same
options as
belongs_to(), as it then calls it.
def self.delegates_to( delegatee, options={} )
classname = options[:class_name] || delegatee.to_s.camelize
belongs_to( delegatee.to_sym, options )
include Biot023::ActsAsDelegator
class_eval( <<-EOS, “_fetch_delegatee”, 1 )
def fetch_delegatee#{ delegatee.to_s }
self.#{ delegatee.to_s } ||= #{ classname }.new
self.#{ delegatee.to_s }
end
EOS
end
before_save do |model|
model.methods.grep( /^fetch_delegatee/ ).each do |mname|
del = model.method( mname ).call
del.save!
end
end
end
`

Cheers again,  
Doug.
