From: transfire@... Date: 2006-07-15T06:03:09+09:00 Subject: Re: Preferred monkeypatching technique Daniel Schierbeck wrote: > Tom Werner 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? > > Not a solution, but: > > > > cut MyCut < Firetruck > def put_out_fire(options = {}) > super(options.merge(:nozzle => :big)) > end > end > > (Trans, can I omit the `MyCut <' part?) Sure. Although, the name provides a handle if you need to dynamically effect the cut later --just like any Ruby class. But you can of course do it annonymously too: Cut.new(Firetruck) do ... end And if you make a module you can "preclude" (in contrast to include) class FireTruck preclude BigFireTruck end T.