On 7/14/06, Tom Werner <tom / helmetstohardhats.org> wrote: > Allow me to present a scenario: > > class Firetruck > def put_out_fire(options = {}) > # code > end > end > > Pretend Firetruck is in a 3rd party application (like Rails) that is > happy to allow plugins to modify core code. Now, let's say I want to > write some code that always adds a certain attribute to the options > hash. I could do this: > > class Firetruck > alias_method :__old_put_out_fire, :put_out_fire > def put_out_fire(options = {}) > __old_put_out_fire(options.merge({:nozzle => :big})) > end > end > > Which works just fine until someone else comes up with a plugin that > wants to modify the same method (doing something similar to me) and just > so happens to also use :__old_put_out_fire as THEIR alias. Now we've got > my plugin's method as the alias calling itself, which leads to, you > know, badness. > > So I'm wondering if there's a better way. Perhaps some way to turn > Firetruck into an ancestor of itself, so to speak, so that my plugin > would create a new Firetruck class, pushing the old Firetruck backward > in the chain and allowing me to call super instead and preventing > alias_method explosions. Or would that just end up causing more havoc? > > Tom > > -- > Tom Werner > Helmets to Hardhats > Software Developer > tom / helmetstohardhats.org > www.helmetstohardhats.org > Here's one way to do it: class Firetruck def put_out_fire(options = {}) p [1, self.class, options] # code end end class Firetruck # get ref to (unbound) old instance method old_put_out_fire = instance_method(:put_out_fire) define_method :put_out_fire do |options| p [2, self.class, options] options ||= { } old_put_out_fire.bind(self).call(options.merge({:nozzle => :big})) end end f = Firetruck.new f.put_out_fire :colour => :red __END__ [2, Firetruck, {:colour=>:red}] [1, Firetruck, {:nozzle=>:big, :colour=>:red}] Note that the method rebinding happens every time you call the method so incurs a fair bit of overhead. Regards, Sean