# Hooking on method invocation

**URL:** <https://rubytalk.org/t/hooking-on-method-invocation/2327>\
**Category:** ruby-talk\
**Created:** [16 October 2002 13:43 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327 "2002-10-16T13:43:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Viking](https://avatars.discourse-cdn.com/v4/letter/v/bc79bd/32.png) [@Viking](https://rubytalk.org/u/Viking)\
**Post date:** [16 October 2002 13:43 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/1 "2002-10-16T13:43:05Z")

</div>

Hello,

Is there a way to hook on invocation of _any_ instance method of an  
object?

My first attempt was to override the send method:

class Foo  
#just ban them  
def send(symbol, \*args)  
puts "blocked"  
end  
end

It works when I do:

foo = Foo.new  
foo.send :something

But it has no effect on “conventional” method invocations. It seems  
that send is not a part of the built-in method dispatch procedure.

I want such functionality to implement ‘write barriers’ for certain  
objects. The idea was to track invocation of writer methods and notify  
object’s observer of changes. If this is achievable by other means,  
any hints will be greatly appreciated.

> **···**
>
> –  
> Eugene

---

<div class="post-metadata">

**Author:** ![Mauricio\_Fernndez](https://avatars.discourse-cdn.com/v4/letter/m/e495f1/32.png) [@Mauricio\_Fernndez](https://rubytalk.org/u/Mauricio_Fernndez)\
**Post date:** [16 October 2002 14:17 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/2 "2002-10-16T14:17:58Z")

</div>

Delegation maybe?

The “barrier keeper” object checks in method\_missing whether a method  
will modify the object or not, notifies the observers if so, and delegates  
the actual work to another object (the one being observed).

The “actual” object would have to provide a list of the methods for which  
notification is needed and what action to perform (possibly via a Proc).

> **···**
>
> On Wed, Oct 16, 2002 at 10:43:05PM +0900, Eugene Zaikonnikov wrote:
> 
> > Hello,
> > 
> > Is there a way to hook on invocation of _any_ instance method of an  
> > object?
> > 
> > My first attempt was to override the send method:
> > 
> > class Foo  
> > #just ban them  
> > def send(symbol, \*args)  
> > puts “blocked”  
> > end  
> > end
> > 
> > It works when I do:
> > 
> > foo = Foo.new  
> > foo.send :something
> > 
> > But it has no effect on “conventional” method invocations. It seems  
> > that send is not a part of the built-in method dispatch procedure.
> > 
> > I want such functionality to implement ‘write barriers’ for certain  
> > objects. The idea was to track invocation of writer methods and notify  
> > object’s observer of changes. If this is achievable by other means,  
> > any hints will be greatly appreciated.
> 
> –  
> \_ \_
> 
> > > \_\_ \_\_ _| |_ \_\_\_ \_ \_\_ \_\_\_ \_\_ \_ \_ \_\_  
> > > '\_ \ / _`| __/__ | '_` \_ \ / ` | ’ \   
> > > ) | (| | |_\_\_ \ | | | | | (_| | | | |  
> > > .\_\_/ \_,_|\ __|__ /| |_| |_|\__,_|_| |\_|  
> > > Running Debian GNU/Linux Sid (unstable)  
> > > batsman dot geo at yahoo dot com
> 
> Turn right here. No! NO! The OTHER right!

---

<div class="post-metadata">

**Author:** ![Avi\_Bryant1](https://avatars.discourse-cdn.com/v4/letter/a/f4b2a3/32.png) [@Avi\_Bryant1](https://rubytalk.org/u/Avi_Bryant1)\
**Post date:** [16 October 2002 18:24 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/3 "2002-10-16T18:24:24Z")

</div>

[viking@funcall.org](mailto:viking@funcall.org) (Eugene Zaikonnikov) wrote in message news:[680a835d.0210160530.4ffa6227@posting.google.com](mailto:680a835d.0210160530.4ffa6227@posting.google.com)…

> Hello,
> 
> Is there a way to hook on invocation of _any_ instance method of an  
> object?

> **[beta4.com](http://beta4.com/advice.c)**
>
> Beta Games

---

<div class="post-metadata">

**Author:** ![William\_Djaja\_Tjokr1](https://avatars.discourse-cdn.com/v4/letter/w/87869e/32.png) [@William\_Djaja\_Tjokr1](https://rubytalk.org/u/William_Djaja_Tjokr1)\
**Post date:** [16 October 2002 19:44 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/4 "2002-10-16T19:44:36Z")

</div>

Hi,

I am sorry that I think the whole discussion has advanced to a new  
level; but to answer the original question, can’t we do a simple thing  
like:

$blocked = true  
(Foo.new.methods - Object.methods).each do |met|  
str = “class Foo\n”  
str \<\< " alias #{met}\_original #{met}\n"  
str \<\< " def #{met} (\*args)\n"  
str \<\< " if $blocked\n"  
str \<\< " puts ‘blocked’\n"  
str \<\< " else\n"  
str \<\< " #{met}\_original(\*args)"  
str \<\< " end\n"  
str \<\< " end\n"  
str \<\< “end”  
eval str  
end

? The code above can easily be modified to pick which methods to block  
(by matching “met” with a regexp), to notify the observer, etc. This is  
of course if we don’t want to go into some aspect-oriented programming, as  
also has been suggested.

Regards,

Bill

> **···**
>
> ============================================================================  
> Eugene Zaikonnikov [viking@funcall.org](mailto:viking@funcall.org) wrote:
> 
> > Hello,
> 
> > Is there a way to hook on invocation of _any_ instance method of an  
> > object?
> 
> > My first attempt was to override the send method:
> 
> > class Foo  
> > #just ban them  
> > def send(symbol, \*args)  
> > puts “blocked”  
> > end  
> > end
> 
> > It works when I do:
> 
> > foo = Foo.new  
> > foo.send :something
> 
> > But it has no effect on “conventional” method invocations. It seems  
> > that send is not a part of the built-in method dispatch procedure.
> 
> > I want such functionality to implement ‘write barriers’ for certain  
> > objects. The idea was to track invocation of writer methods and notify  
> > object’s observer of changes. If this is achievable by other means,  
> > any hints will be greatly appreciated.
> 
> > –  
> > Eugene

---

<div class="post-metadata">

**Author:** ![Mauricio\_Fernndez](https://avatars.discourse-cdn.com/v4/letter/m/e495f1/32.png) [@Mauricio\_Fernndez](https://rubytalk.org/u/Mauricio_Fernndez)\
**Post date:** [16 October 2002 15:24 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/5 "2002-10-16T15:24:26Z")

</div>

Code follows:

module Observable

# pretty lame and useless, but I didn’t feel like removing it after all this

# typing; it could probably automate the generation of the list in a

# sensible way

def get\_method\_list  
  
end  
end

class BarrierKeeper  
def initialize(obj)  
@theobj = obj  
end

def method\_missing(sym,\*args)  
h = @theobj.get\_method\_list  
ret = true  
ret = h[sym].call if h[sym]  
@theobj.send(sym, \*args) if ret  
end

end

class AnObject  
include Observable

def initialize  
@block\_proc = proc { puts “ACTION: Blocked!”; false }  
@notify\_proc = proc do  
puts “ACTION: notify the observers; w/ ‘require "observer"’”  
true  
end  
end

def amethod  
puts “METH: You won’t see this”  
end

def another  
puts “METH: This one is not blocked.”  
end

def get\_method\_list  
{ :amethod =\> @block\_proc, :another =\> @notify\_proc }  
end

end

a = AnObject.new  
theproxy = BarrierKeeper.new a  
theproxy.amethod  
theproxy.another

> **···**
>
> On Wed, Oct 16, 2002 at 11:17:58PM +0900, Mauricio Fernández wrote:
> 
> > On Wed, Oct 16, 2002 at 10:43:05PM +0900, Eugene Zaikonnikov wrote:
> > 
> > > Hello,
> > > 
> > > Is there a way to hook on invocation of _any_ instance method of an  
> > > object?
> > > 
> > > My first attempt was to override the send method:
> > > 
> > > class Foo  
> > > #just ban them  
> > > def send(symbol, \*args)  
> > > puts “blocked”  
> > > end  
> > > end
> > > 
> > > It works when I do:
> > > 
> > > foo = Foo.new  
> > > foo.send :something
> > > 
> > > But it has no effect on “conventional” method invocations. It seems  
> > > that send is not a part of the built-in method dispatch procedure.
> > > 
> > > I want such functionality to implement ‘write barriers’ for certain  
> > > objects. The idea was to track invocation of writer methods and notify  
> > > object’s observer of changes. If this is achievable by other means,  
> > > any hints will be greatly appreciated.
> > 
> > Delegation maybe?
> 
> –  
> \_ \_
> 
> > > \_\_ \_\_ _| |_ \_\_\_ \_ \_\_ \_\_\_ \_\_ \_ \_ \_\_  
> > > '\_ \ / _`| __/__ | '_` \_ \ / ` | ’ \   
> > > ) | (| | |_\_\_ \ | | | | | (_| | | | |  
> > > .\_\_/ \_,_|\ __|__ /| |_| |_|\__,_|_| |\_|  
> > > Running Debian GNU/Linux Sid (unstable)  
> > > batsman dot geo at yahoo dot com
> 
> Q: What’s the big deal about rm, I have been deleting stuff for years? And  
> never lost anything.. oops!  
> A: …  
> – From the Frequently Unasked Questions

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [17 October 2002 09:27 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/6 "2002-10-17T09:27:06Z")

</div>

> [beta4.com](http://beta4.com/advice.c)

Look at fwrap, I think that you can have a better interface with it

[http://www.franz.com/support/documentation/6.2/doc/fwrappers-and-advice.htm](http://www.franz.com/support/documentation/6.2/doc/fwrappers-and-advice.htm)

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard1](https://avatars.discourse-cdn.com/v4/letter/a/f19dbf/32.png) [@Ara.T.Howard1](https://rubytalk.org/u/Ara.T.Howard1)\
**Post date:** [16 October 2002 16:23 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/7 "2002-10-16T16:23:56Z")

</div>

> > > Is there a way to hook on invocation of _any_ instance method of an  
> > > object?  
> > > …  
> > > [snip]  
> > > …
> 
> Code follows:
> 
> module Observable  
> …  
> [snip]  
> …  
> theproxy.another

that seems pretty complicated - it seems like what is needed is a  
specialization of a class, espcially since only the assignment methods need  
overridden. isn’t this _the_ job of inheritence? eg:

def assignment\_hook(\*args)  
re = /`([^‘]+)’/  
m = re.match caller(1)[0]  
m or raise ‘FAILED TO LOOKUP METHOD NAME’  
methodname = m[1]

# notify observer here…

puts “hook for #{methodname}(#{args.join ‘,’}) called…”  
end

class Original  
def foo=(\*args)  
# do something  
end  
end

class Hooked \< Original  
def foo=(\*args)  
assignment\_hook \*args  
super \*args  
end  
end

h = Hooked.new  
h.foo= 0,1,2 # → hook for foo=(0,1,2) called…

simple : yes  
fast : yes  
safe : yes  
typing : yes

-ara

> **···**
>
> –
> 
> ====================================
> 
> > Ara Howard  
> > NOAA Forecast Systems Laboratory  
> > Information and Technology Services  
> > Data Systems Group  
> > R/FST 325 Broadway  
> > Boulder, CO 80305-3328  
> > Email: [ahoward@fsl.noaa.gov](mailto:ahoward@fsl.noaa.gov)  
> > Phone: 303-497-7238  
> > Fax: 303-497-7259  
> > ====================================

---

<div class="post-metadata">

**Author:** ![Mauricio\_Fernndez](https://avatars.discourse-cdn.com/v4/letter/m/e495f1/32.png) [@Mauricio\_Fernndez](https://rubytalk.org/u/Mauricio_Fernndez)\
**Post date:** [16 October 2002 17:09 UTC](https://rubytalk.org/t/hooking-on-method-invocation/2327/8 "2002-10-16T17:09:23Z")

</div>

> > > > Is there a way to hook on invocation of _any_ instance method of  
> > > > an  
> > > > object?  
> > > > …  
> > > > [snip]  
> > > > …
> > 
> > Code follows:
> > 
> > module Observable  
> > …  
> > [snip]  
> > …  
> > theproxy.another
> 
> that seems pretty complicated - it seems like what is needed is a  
> specialization of a class, espcially since only the assignment methods  
> need  
> overridden. isn’t this _the_ job of inheritence? eg:

In fact this could be meaningful w/ any method that changes the state  
of an object, assignment or not.

> def assignment\_hook(\*args)  
> re = /`([^‘]+)’/  
> m = re.match caller(1)[0]  
> m or raise ‘FAILED TO LOOKUP METHOD NAME’  
> methodname = m[1]
> 
> # notify observer here…
> 
> puts “hook for #{methodname}(#{args.join ‘,’}) called…”  
> end
> 
> class Original  
> def foo=(\*args)  
> # do something  
> end  
> end
> 
> class Hooked \< Original  
> def foo=(\*args)  
> assignment\_hook \*args  
> super \*args  
> end  
> end
> 
> h = Hooked.new  
> h.foo= 0,1,2 # → hook for foo=(0,1,2) called…
> 
> simple : yes  
> fast : yes  
> safe : yes  
> typing : yes

Yes, but you have to redefine all the methods needing some kind of  
“write barrier”. The way I showed before, the BarrierKeeper is in fact a  
proxy which decides whether a method call should be forwarded or not;  
and it is easily mixed with the Observer pattern.

What I don’t like about inheritance is having to type  
def method(\*args)  
hook(\*args)  
super \*args  
end  
which is of course more of a matter of taste. And then again, it would be  
possible to create something like  
set\_barrier :method\_name, proc { |method, args| … }  
which could work either via inheritance or delegation.

Delegation gives you more freedom, for a BarrierKeeper could potentially  
take care of different objects during runtime, even those of an  
unknown class! If you use inheritance, you end up having to know the  
class of the object _or_ using lots of singleton methods. And you’d have  
to use the evil eval 🙂

Guess it’s just another case of object vs class design pattern…

> **···**
>
> On Wed, Oct 16, 2002 at 04:10:14PM +0000, ahoward wrote:
> 
> –  
> \_ \_
> 
> > > \_\_ \_\_ _| |_ \_\_\_ \_ \_\_ \_\_\_ \_\_ \_ \_ \_\_  
> > > '\_ \ / _`| __/__ | '_` \_ \ / ` | ’ \   
> > > ) | (| | |_\_\_ \ | | | | | (_| | | | |  
> > > .\_\_/ \_,_|\ __|__ /| |_| |_|\__,_|_| |\_|  
> > > Running Debian GNU/Linux Sid (unstable)  
> > > batsman dot geo at yahoo dot com
> 
> I once witnessed a long-winded, month-long flamewar over the use of  
> mice vs. trackballs… It was very silly.  
> – Matt Welsh
