From: Joel VanderWerf Date: 2004-10-30T13:35:21+09:00 Subject: Re: extending instance methods from a class object William Morgan wrote: > Hi all, > > I'm currently drowning in a pool of instance_methods and define_methods > and I can't seem to get out. I know there's an elegant solution > somewhere.... > > I have a Class object klass. It has an instance method meth(). I'd like > to "extend" meth() so that when it's called, the output is changed---I > want to call the original meth(), tweak its result, and then return it. > I need to return a Class object that has this tweak in place; I can > either change klass and return that or I can subclass it and return the > subclass. > > Something like: > > def tweaked_class(klass) > old_meth = klass.instance_method(:to_html) > klass.define_method(:meth) do |*a| > r = old_meth(*a) > # ... transform r ... > r > end > klass > end > > But that doesn't work, and I might be on the wrong track completely. > So what's the best way to do this? > > Thanks, > Here are two ways. There are probably more, knowing ruby :) def tweak(klass, old_meth, new_meth) if old_meth == new_meth old_meth_unbound = klass.instance_method(old_meth) klass.class_eval do define_method(new_meth) do |*args| yield old_meth_unbound.bind(self).call(*args) end end else klass.class_eval do define_method(new_meth) do |*args| yield send(old_meth, *args) end end end klass end class Foo def whazzup; "nothing"; end end tweak(Foo, :whazzup, :whaddaya) do |r| r + " much" end p Foo.new.whaddaya tweak(Foo, :whazzup, :whazzup) do |r| r + " else" end p Foo.new.whazzup