module MethodCalledMagic
def method_added(id) @level ||= 0
return if @level == 1 @level += 1
alias_method “real#{id}”, id
module_eval <<-EOF
def #{id}(*a,&b)
puts “You called #{self.inspect}##{id}” real#{id}(*a,&b)
end
EOF @level -= 1
end
def self.extend_object(obj)
obj.send :define_method, :method_missing do |id,*a|
puts “You called #{self.class}##{id}”
super id
end
super
end
end
Promise us you will never show this code to anyone who is
considering ruby. They will run away screaming halfway
through the first method.
I thought it was a simple request ( -that an object know what
messages/methods was passed to it).
Batsman solution provides rediversions using extend_object and method_added
(wc looks kludgy imho). It works, but I hope there are more “cleaner”
solutions to come.
I thought it was a simple request ( -that an object know what
messages/methods was passed to it).
Batsman solution provides rediversions using extend_object and method_added
(wc looks kludgy imho). It works, but I hope there are more “cleaner”
solutions to come.
I think the reason it’s not around by default is that it wouldn’t
realistically be used
much, and it’s a waste of resources if it’s not used.
Generally, if an object’s method is called, it knows about it in the
sense that the
method executes. Calling another method #method_called with the symbol every
time any method is called isn’t very useful except in your example where
you want
to wrap every method in the exact same way. If you want to wrap certain
methods
then it’s clearer now to just alias and redefine.
In the future, there will be special wrappnig hooks for methods, so the
kludgy code
might get a little less kludgy (but not much). Theoretically you could
implement some
of the discussed wrapping by having #method_called be called before
every method
call (excluding #method_called itself, of course), and #method_finished
after every
method, and then use a big case expression against the symbols. However,
it’s more
useful/elegant from the programmer’s perspective if you wrap single
methods at a time.
In otherwords, if you want to blanket wrap all methods in a class (which
essentially
is what you’re doing when you execute #method_called before every other
method),
it’s always going to be kludgy, although you can hide that kludge
elsewhere (like in an
aspect oriented programming module, for example).
That’s my perspective, at least. I hope some of it made some sense.