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