# Preferred monkeypatching technique

**URL:** <https://rubytalk.org/t/preferred-monkeypatching-technique/28947>\
**Category:** ruby-talk\
**Created:** [13 July 2006 23:28 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947 "2006-07-13T23:28:12Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tom\_Werner1](https://avatars.discourse-cdn.com/v4/letter/t/919ad9/32.png) [@Tom\_Werner1](https://rubytalk.org/u/Tom_Werner1)\
**Post date:** [13 July 2006 23:28 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/1 "2006-07-13T23:28:12Z")

</div>

Allow me to present a scenario:

class Firetruck  
&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
&nbsp;&nbsp;&nbsp;&nbsp;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  
&nbsp;&nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
&nbsp;&nbsp;&nbsp;&nbsp;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](mailto:tom@helmetstohardhats.org)  
> [www.helmetstohardhats.org](http://www.helmetstohardhats.org)

---

<div class="post-metadata">

**Author:** ![Eric\_Hodel1](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@Eric\_Hodel1](https://rubytalk.org/u/Eric_Hodel1)\
**Post date:** [13 July 2006 23:45 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/2 "2006-07-13T23:45:59Z")

</div>

You just described subclasses:

class BigNozzleFiretruck \< Firetruck

&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options = options.merge :nozzle =\> :big  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super options  
&nbsp;&nbsp;&nbsp;end

end

> **···**
>
> On Jul 13, 2006, at 4:28 PM, Tom Werner wrote:
> 
> > Allow me to present a scenario:
> > 
> > class Firetruck  
> > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > &nbsp;&nbsp;&nbsp;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  
> > &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > &nbsp;&nbsp;&nbsp;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?
> 
> --  
> Eric Hodel - drbrain@segment7.net - [http://blog.segment7.net](http://blog.segment7.net)  
> This implementation is HODEL-HASH-9600 compliant
> 
> [http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![Daniel\_Berger2](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/daniel_berger2/32/2243_2.png) [@Daniel\_Berger2](https://rubytalk.org/u/Daniel_Berger2)\
**Post date:** [13 July 2006 23:50 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/3 "2006-07-13T23:50:09Z")

</div>

Tom Werner wrote:

> Allow me to present a scenario:
> 
> class Firetruck  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> &nbsp;&nbsp;&nbsp;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  
> &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> &nbsp;&nbsp;&nbsp;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

Perhaps add a namespace?

# monkey.rb  
class Foo  
&nbsp;&nbsp;&nbsp;def monkey  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"hello"  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def test  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"test"  
&nbsp;&nbsp;&nbsp;end  
end

module Test  
&nbsp;&nbsp;&nbsp;class Foo \< ::Foo  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def monkey  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"world"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end  
end

foo1 = Foo.new  
foo2 = Test::Foo.new

foo1.monkey # "hello"  
foo2.monkey # "world"  
foo1.test # "test"  
foo2.test # "test"

Hm, this thread actually gives me more fodder for my previous idea of having objects store aliases for later reference. We could then emit a warning if you define an alias that already exists. 🙂

HTH,

Dan

---

<div class="post-metadata">

**Author:** ![Sean\_O\_Halpin](https://avatars.discourse-cdn.com/v4/letter/s/ac91a4/32.png) [@Sean\_O\_Halpin](https://rubytalk.org/u/Sean_O_Halpin)\
**Post date:** [13 July 2006 23:55 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/4 "2006-07-13T23:55:51Z")

</div>

Here's one way to do it:

class Firetruck  
&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;p [1, self.class, options]  
&nbsp;&nbsp;&nbsp;&nbsp;# code  
&nbsp;&nbsp;end  
end

class Firetruck  
&nbsp;&nbsp;# get ref to (unbound) old instance method  
&nbsp;&nbsp;old\_put\_out\_fire = instance\_method(:put\_out\_fire)  
&nbsp;&nbsp;define\_method :put\_out\_fire do |options|  
&nbsp;&nbsp;&nbsp;&nbsp;p [2, self.class, options]  
&nbsp;&nbsp;&nbsp;&nbsp;options ||= { }  
&nbsp;&nbsp;&nbsp;&nbsp;old\_put\_out\_fire.bind(self).call(options.merge({:nozzle =\> :big}))  
&nbsp;&nbsp;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

> **···**
>
> On 7/14/06, Tom Werner \<tom@helmetstohardhats.org\> wrote:
> 
> > Allow me to present a scenario:
> > 
> > class Firetruck  
> > &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > &nbsp;&nbsp;&nbsp;&nbsp;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  
> > &nbsp;&nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > &nbsp;&nbsp;&nbsp;&nbsp;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](http://www.helmetstohardhats.org)

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [14 July 2006 00:49 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/5 "2006-07-14T00:49:42Z")

</div>

Hi --

> Allow me to present a scenario:
> 
> class Firetruck  
> &nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> &nbsp;&nbsp;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  
> &nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> &nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> &nbsp;&nbsp;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?

I don't know whether it qualifies as "monkeypatching" (I always  
thought that meant doing something sloppy and ill-advised, which I  
hope I'm not 🙂 but see if this helps:

&nbsp;&nbsp;&nbsp;class FireTruck  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p options  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;FireTruck.class\_eval do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = instance\_method(:put\_out\_fire)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(:put\_out\_fire) do |options|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.bind(self).call(options.merge({ :nozzle =\> "big" }))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;FireTruck.new.put\_out\_fire(1 =\> 2)

&nbsp;&nbsp;&nbsp;# Now someone else uses the alias:  
&nbsp;&nbsp;&nbsp;class FireTruck  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias old\_put\_out\_fire put\_out\_fire  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "New version!"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;old\_put\_out\_fire(options)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;FireTruck.new.put\_out\_fire(1 =\> 2)

Output:

{1=\>2, :nozzle=\>"big"}  
New version!  
{1=\>2, :nozzle=\>"big"}

David

> **···**
>
> On Fri, 14 Jul 2006, Tom Werner wrote:
> 
> --  
> [http://www.rubypowerandlight.com](http://www.rubypowerandlight.com) =\> Ruby/Rails training & consultancy  
> [Ruby for Rails](http://www.manning.com/black) =\> RUBY FOR RAILS (reviewed on  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Slashdot, 7/12/2006!)  
> [http://dablog.rubypal.com](http://dablog.rubypal.com) =\> D[avid]A[.]B[lack's][Web]log  
> dblack@wobblini.net =\> me

---

<div class="post-metadata">

**Author:** ![Daniel\_DeLorme](https://avatars.discourse-cdn.com/v4/letter/d/9d8465/32.png) [@Daniel\_DeLorme](https://rubytalk.org/u/Daniel_DeLorme)\
**Post date:** [14 July 2006 01:03 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/6 "2006-07-14T01:03:15Z")

</div>

Tom Werner wrote:

> Allow me to present a scenario:
> 
> class Firetruck  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> &nbsp;&nbsp;&nbsp;end  
> end

Here's what I'd do to keep it clean:

module FastFiretruck  
&nbsp;&nbsp;&nbsp;def initialize(\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.extend FastFiretruck::Obj  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;module Obj  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end  
end  
Firetruck.class\_eval{ include FastFiretruck }

Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_Martin](https://avatars.discourse-cdn.com/v4/letter/d/dc4da7/32.png) [@Daniel\_Martin](https://rubytalk.org/u/Daniel_Martin)\
**Post date:** [14 July 2006 12:25 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/7 "2006-07-14T12:25:28Z")

</div>

Tom Werner \<tom@helmetstohardhats.org\> writes:

> class Firetruck  
> &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> &nbsp;&nbsp;&nbsp;end  
> end

It seems to me that you're asking for a ruby version of gensym. (See  
any lisp reference that talks about lisp macro writing) So let's try  
to make something like that:

# In the framework core

class Firetruck  
&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;puts "Extinguishing with options #{options.inspect}"  
&nbsp;&nbsp;end  
end

# In plugin1

class Symbol  
&nbsp;&nbsp;def Symbol.gensym  
&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count ||= 0  
&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count += 1  
&nbsp;&nbsp;&nbsp;&nbsp;("\_\_gensym\_\_%X" % @@gensym\_count).intern  
&nbsp;&nbsp;end  
end

class Firetruck  
&nbsp;&nbsp;oldmethsym = Symbol.gensym  
&nbsp;&nbsp;alias\_method oldmethsym, :put\_out\_fire  
&nbsp;&nbsp;class\_eval %Q[  
&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{oldmethsym}(options.merge({:nozzle =\> :big}))  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;]  
end

## Now, in plugin 2

# Note that the same exact code is included for gensym, but  
# that this isn't a problem  
class Symbol  
&nbsp;&nbsp;def Symbol.gensym  
&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count ||= 0  
&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count += 1  
&nbsp;&nbsp;&nbsp;&nbsp;("\_\_gensym\_\_%X" % @@gensym\_count).intern  
&nbsp;&nbsp;end  
end

class Firetruck  
&nbsp;&nbsp;oldmethsym = Symbol.gensym  
&nbsp;&nbsp;alias\_method oldmethsym, :put\_out\_fire  
&nbsp;&nbsp;class\_eval %Q[  
&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{oldmethsym}(options.merge({:material =\> :foam}))  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;]  
end

> **···**
>
> ---------------------------------
> 
> Now in irb:  
> irb(main):132:0\> load "c:\\temp\\firetruck.rb"  
> =\> true  
> irb(main):133:0\> Firetruck.new.put\_out\_fire  
> Extinguishing with options {:nozzle=\>:big, :material=\>:foam}  
> =\> nil
> 
> Now, what I'd really like for doing stuff like this is an easy ruby  
> equivalent of lisp's quasi-quote, with the ability to nest levels of  
> quotation easily. As it is, %Q combined with an eval that takes a  
> string helps in many practical cases where you want something vaguely  
> like bits of lisp's macro facility, but it's cumbersome to write  
> things like macro-generating macros, for example.

---

<div class="post-metadata">

**Author:** ![Daniel\_Schierbeck](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@Daniel\_Schierbeck](https://rubytalk.org/u/Daniel_Schierbeck)\
**Post date:** [14 July 2006 20:05 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/8 "2006-07-14T20:05:05Z")

</div>

Tom Werner wrote:

> Allow me to present a scenario:
> 
> class Firetruck  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> &nbsp;&nbsp;&nbsp;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  
> &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> &nbsp;&nbsp;&nbsp;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:

&nbsp;&nbsp;&nbsp;\<[http://rcrchive.net/rcr/show/321&gt](http://rcrchive.net/rcr/show/321&gt);

&nbsp;&nbsp;&nbsp;cut MyCut \< Firetruck  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(options.merge(:nozzle =\> :big))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

(Trans, can I omit the `MyCut \<' part?)

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_Berger2](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/daniel_berger2/32/2243_2.png) [@Daniel\_Berger2](https://rubytalk.org/u/Daniel_Berger2)\
**Post date:** [13 July 2006 23:58 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/9 "2006-07-13T23:58:18Z")

</div>

Eric Hodel wrote:

> **···**
>
> > On Jul 13, 2006, at 4:28 PM, Tom Werner wrote:
> > 
> > > Allow me to present a scenario:
> > > 
> > > class Firetruck  
> > > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > > &nbsp;&nbsp;&nbsp;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  
> > > &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > > &nbsp;&nbsp;&nbsp;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?
> > 
> > You just described subclasses:
> > 
> > class BigNozzleFiretruck \< Firetruck
> > 
> > &nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;options = options.merge :nozzle =\> :big  
> > &nbsp;&nbsp;&nbsp;&nbsp;super options  
> > &nbsp;&nbsp;end
> > 
> > end
> > 
> > --Eric Hodel - drbrain@segment7.net - [http://blog.segment7.net](http://blog.segment7.net)  
> > This implementation is HODEL-HASH-9600 compliant
> > 
> > [http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)
> 
> Or that. 🙂
> 
> - Dan

---

<div class="post-metadata">

**Author:** ![Tom\_Werner1](https://avatars.discourse-cdn.com/v4/letter/t/919ad9/32.png) [@Tom\_Werner1](https://rubytalk.org/u/Tom_Werner1)\
**Post date:** [14 July 2006 00:04 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/10 "2006-07-14T00:04:00Z")

</div>

Daniel Berger wrote:

> Perhaps add a namespace?

Eric Hodel wrote:

> You just described subclasses:

Well, the idea is that the 3rd party software is going to be using whatever classes it has always used, so just creating a subclass doesn't get me anywhere because the 3rd party app (i.e. Rails) doesn't give a hoot about my BigNozzleFiretruck.

Similarly, creating a separate namespace via a module has the same problem. I can do that all day long but the 3rd party app won't care (or is there a way to MAKE it care?).

It occurs to me that the use of GUIDs might be in order:

alias\_method :put\_out\_fire\_baee44c012cb11dbac5d0800200c9a66, :put\_out\_fire

Ugly but functional?

Tom

> **···**
>
> --  
> Tom Werner  
> Helmets to Hardhats  
> Software Developer  
> tom@helmetstohardhats.org  
> [www.helmetstohardhats.org](http://www.helmetstohardhats.org)

---

<div class="post-metadata">

**Author:** ![JM1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@JM1](https://rubytalk.org/u/JM1)\
**Post date:** [14 July 2006 00:40 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/11 "2006-07-14T00:40:46Z")

</div>

Sounded to me that perhaps he was talking about the problems that I normally  
associate with dependency injection\* - he's trying to get an existing class  
to create an object of a new class, rather than the thing that it normally  
uses. In this case, I think what he's saying is that the existing class is  
going to instantiate a Firetruck; having BigNozzleFiretruck exist as a  
possibility of an object that could be instantiated doesn't address the  
whole problem.

Do articles like  
[http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc](http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc)  
address the sort of thing you're talking about, Tom?

- James Moore

\* A phrase that, unfortunately, I use with wild abandon and less meaning  
than perhaps I should.

> **···**
>
> > -----Original Message-----  
> > You just described subclasses:
> > 
> > class BigNozzleFiretruck \< Firetruck
> > 
> > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options = options.merge :nozzle =\> :big  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super options  
> > &nbsp;&nbsp;&nbsp;end
> > 
> > end

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [14 July 2006 03:32 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/12 "2006-07-14T03:32:45Z")

</div>

dblack@wobblini.net wrote:

> I don't know whether it qualifies as "monkeypatching" (I always  
> thought that meant doing something sloppy and ill-advised, which I  
> hope I'm not 🙂 but see if this helps:

Actually it was only last week that I first saw this term  
being used in the Ruby community. I wonder if it's too  
late to squash it?

Hal

---

<div class="post-metadata">

**Author:** ![Logan\_Capaldo](https://avatars.discourse-cdn.com/v4/letter/l/7ea924/32.png) [@Logan\_Capaldo](https://rubytalk.org/u/Logan_Capaldo)\
**Post date:** [14 July 2006 03:54 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/13 "2006-07-14T03:54:04Z")

</div>

And I thought the blah = instance\_method closure trick was cool, but this beats the pants off it.

Note that you can use

Firetruck.send(:include, FastFiretruck)

or in 1.9 Firetruck.funcall(:include, FastFiretruck) to bypass the need for a block.

> **···**
>
> On Jul 13, 2006, at 9:03 PM, Daniel DeLorme wrote:
> 
> > Tom Werner wrote:
> > 
> > > Allow me to present a scenario:  
> > > class Firetruck  
> > > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > > &nbsp;&nbsp;&nbsp;end  
> > > end
> > 
> > Here's what I'd do to keep it clean:
> > 
> > module FastFiretruck  
> > &nbsp;&nbsp;def initialize(\*args)  
> > &nbsp;&nbsp;&nbsp;&nbsp;super  
> > &nbsp;&nbsp;&nbsp;&nbsp;self.extend FastFiretruck::Obj  
> > &nbsp;&nbsp;end  
> > &nbsp;&nbsp;module Obj  
> > &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;end  
> > end  
> > Firetruck.class\_eval{ include FastFiretruck }
> > 
> > Daniel

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [14 July 2006 04:40 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/14 "2006-07-14T04:40:16Z")

</div>

Daniel DeLorme wrote:

> Tom Werner wrote:  
> \> Allow me to present a scenario:  
> \>  
> \> class Firetruck  
> \> def put\_out\_fire(options = {})  
> \> # code  
> \> end  
> \> end
> 
> Here's what I'd do to keep it clean:
> 
> module FastFiretruck  
> &nbsp;&nbsp;&nbsp;def initialize(\*args)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.extend FastFiretruck::Obj  
> &nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;module Obj  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end  
> Firetruck.class\_eval{ include FastFiretruck }

That only works because there is no initialize method defined in  
Firetruck. You might as well have done:

&nbsp;&nbsp;class Firetruck  
&nbsp;&nbsp;&nbsp;&nbsp;def initialize(\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.extend FastFiretruck  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

&nbsp;&nbsp;module FastFiretruck  
&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

If you're just after one method you can alway use Facets'  
module#wrap\_method. If you want to do aspecting (is that what this  
"monkeypatching" is all about?), well I would love to see a Cut  
implementation, but short of that, I've been working on  
#instance\_interception. It still has some kinks, but it essentially  
works.

class Module

&nbsp;&nbsp;def instance\_interception(&block)  
&nbsp;&nbsp;&nbsp;&nbsp;@instance\_interception ||= Module.new do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def self.append\_features(mod)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;append\_features\_without\_instance\_interception( mod )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;@instance\_interception.module\_eval(&block) if block\_given?  
&nbsp;&nbsp;&nbsp;&nbsp;@instance\_interception  
&nbsp;&nbsp;end

&nbsp;&nbsp;private :instance\_interception

&nbsp;&nbsp;alias\_method :append\_features\_without\_instance\_interception,  
:append\_features

&nbsp;&nbsp;# Append features

&nbsp;&nbsp;def append\_features( mod )

&nbsp;&nbsp;&nbsp;&nbsp;aspect = instance\_interception  
&nbsp;&nbsp;&nbsp;&nbsp;aspect.\_\_send\_\_( :append\_features\_without\_instance\_interception,  
mod )

&nbsp;&nbsp;&nbsp;&nbsp;aspect.instance\_methods.each do |meth|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if mod.method\_defined?( meth )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aspect.advise( mod, meth )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;append\_features\_without\_instance\_interception( mod )

&nbsp;&nbsp;&nbsp;&nbsp;#if mod.instance\_of? Module  
&nbsp;&nbsp;&nbsp;&nbsp;aspect.\_\_send\_\_( :append\_features\_without\_instance\_interception,  
mod.\_\_send\_\_(:instance\_interception) )  
&nbsp;&nbsp;&nbsp;&nbsp;#end

&nbsp;&nbsp;end

&nbsp;&nbsp;# Apply the around advice.

&nbsp;&nbsp;def advise( mod, meth )  
&nbsp;&nbsp;&nbsp;&nbsp;advice = instance\_method( meth )  
&nbsp;&nbsp;&nbsp;&nbsp;instance\_target = mod.instance\_method(meth)  
&nbsp;&nbsp;&nbsp;&nbsp;mod.\_\_send\_\_( :define\_method, meth ) { |\*args| #, &blk|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target = instance\_target.bind( self )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(class \<\< target; self; end).class\_eval { define\_method( :super  
){ call( \*args ) } }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;advice.bind( self ).call( target, \*args ) #, &blk )  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;end

&nbsp;&nbsp;# If a method is added to the module/class that is advised.

&nbsp;&nbsp;def method\_added( meth )  
&nbsp;&nbsp;&nbsp;&nbsp;return if @method\_added\_short  
&nbsp;&nbsp;&nbsp;&nbsp;if instance\_interception.method\_defined?( meth )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;include instance\_interception  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@method\_added\_short = true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance\_interception.advise( self, meth )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@method\_added\_short = false  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

end

# EXAMPLE

module A

&nbsp;&nbsp;def f ; "F" ; end  
&nbsp;&nbsp;def g ; "G" ; end

&nbsp;&nbsp;instance\_interception do  
&nbsp;&nbsp;&nbsp;&nbsp;def f( target, \*args, &blk )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'{' + target.super + '}'  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;def g( target, \*args, &blk )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'{' + target.super + '}'  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

end

class X  
&nbsp;&nbsp;def f ; super ; end  
&nbsp;&nbsp;include A  
&nbsp;&nbsp;def g ; super ; end  
end

x = X.new  
p x.f  
p x.g

T.

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [14 July 2006 05:17 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/15 "2006-07-14T05:17:39Z")

</div>

Daniel DeLorme wrote:

> Tom Werner wrote:  
> \> Allow me to present a scenario:  
> \>  
> \> class Firetruck  
> \> def put\_out\_fire(options = {})  
> \> # code  
> \> end  
> \> end
> 
> Here's what I'd do to keep it clean:
> 
> module FastFiretruck  
> &nbsp;&nbsp;&nbsp;def initialize(\*args)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.extend FastFiretruck::Obj  
> &nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;module Obj  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end  
> Firetruck.class\_eval{ include FastFiretruck }

Hey, thanks Daniel! You actaully led me to a new potential approach.  
Here, try this:

class Module  
&nbsp;&nbsp;def monkey\_patch(mod)  
&nbsp;&nbsp;&nbsp;&nbsp;\_new = method(:new)  
&nbsp;&nbsp;&nbsp;&nbsp;\_allocate = method(:allocate)  
&nbsp;&nbsp;&nbsp;&nbsp;(class \<\< self; self; end).class\_eval do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(:new) do |\*args|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o = \_new.call(\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o.extend mod  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(:allocate) do |\*args|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o = \_allocate.call(\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o.extend mod  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

# EXAMPLE

class Firetruck  
&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"put out #{options}"  
&nbsp;&nbsp;&nbsp;end  
end

module FastFiretruck

&nbsp;&nbsp;def put\_out\_fire(options = {})  
&nbsp;&nbsp;&nbsp;&nbsp;super({:fast =\> "please!"}.merge(options))  
&nbsp;&nbsp;end  
end

Firetruck.monkey\_patch(FastFiretruck)

ft = Firetruck.new  
p ft.put\_out\_fire

T.

---

<div class="post-metadata">

**Author:** ![Logan\_Capaldo](https://avatars.discourse-cdn.com/v4/letter/l/7ea924/32.png) [@Logan\_Capaldo](https://rubytalk.org/u/Logan_Capaldo)\
**Post date:** [14 July 2006 17:02 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/16 "2006-07-14T17:02:42Z")

</div>

Neat idea, gensym in Ruby. I would suggest making it thread-safe though:

% cat gensym.rb  
require 'mutex'  
class Symbol  
&nbsp;&nbsp;&nbsp;GensymLock = Mutex.new  
&nbsp;&nbsp;&nbsp;def self.gensym  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GensymLock.synchronize {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count ||= 0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count += 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;("\_\_gensym\_\_%X" % @@gensym\_count).intern  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;end  
end

And just require it whenever you need it.

require 'gensym'  
sym = Symbol.gensym  
alias\_method sym, :blah

> **···**
>
> On Jul 14, 2006, at 8:25 AM, Daniel Martin wrote:
> 
> > Tom Werner \<tom@helmetstohardhats.org\> writes:
> > 
> > > class Firetruck  
> > > &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > > &nbsp;&nbsp;&nbsp;end  
> > > end
> > 
> > It seems to me that you're asking for a ruby version of gensym. (See  
> > any lisp reference that talks about lisp macro writing) So let's try  
> > to make something like that:
> > 
> > # In the framework core
> > 
> > class Firetruck  
> > &nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;puts "Extinguishing with options #{options.inspect}"  
> > &nbsp;&nbsp;end  
> > end
> > 
> > # In plugin1
> > 
> > class Symbol  
> > &nbsp;&nbsp;def Symbol.gensym  
> > &nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count ||= 0  
> > &nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count += 1  
> > &nbsp;&nbsp;&nbsp;&nbsp;("\_\_gensym\_\_%X" % @@gensym\_count).intern  
> > &nbsp;&nbsp;end  
> > end
> > 
> > class Firetruck  
> > &nbsp;&nbsp;oldmethsym = Symbol.gensym  
> > &nbsp;&nbsp;alias\_method oldmethsym, :put\_out\_fire  
> > &nbsp;&nbsp;class\_eval %Q[  
> > &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{oldmethsym}(options.merge({:nozzle =\> :big}))  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;]  
> > end
> > 
> > ## Now, in plugin 2
> > 
> > # Note that the same exact code is included for gensym, but  
> > # that this isn't a problem  
> > class Symbol  
> > &nbsp;&nbsp;def Symbol.gensym  
> > &nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count ||= 0  
> > &nbsp;&nbsp;&nbsp;&nbsp;@@gensym\_count += 1  
> > &nbsp;&nbsp;&nbsp;&nbsp;("\_\_gensym\_\_%X" % @@gensym\_count).intern  
> > &nbsp;&nbsp;end  
> > end

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [14 July 2006 21:03 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/17 "2006-07-14T21:03:09Z")

</div>

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:
> 
> &nbsp;&nbsp;&nbsp;\<[http://rcrchive.net/rcr/show/321&gt](http://rcrchive.net/rcr/show/321&gt);
> 
> &nbsp;&nbsp;&nbsp;cut MyCut \< Firetruck  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(options.merge(:nozzle =\> :big))  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;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:

&nbsp;&nbsp;Cut.new(Firetruck) do  
&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;end

And if you make a module you can "preclude" (in contrast to include)

&nbsp;&nbsp;class FireTruck  
&nbsp;&nbsp;&nbsp;&nbsp;preclude BigFireTruck  
&nbsp;&nbsp;end

T.

---

<div class="post-metadata">

**Author:** ![Tom\_Werner1](https://avatars.discourse-cdn.com/v4/letter/t/919ad9/32.png) [@Tom\_Werner1](https://rubytalk.org/u/Tom_Werner1)\
**Post date:** [14 July 2006 21:06 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/18 "2006-07-14T21:06:05Z")

</div>

Daniel Schierbeck wrote:

> Tom Werner wrote:
> 
> > Allow me to present a scenario:
> > 
> > class Firetruck  
> > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > &nbsp;&nbsp;&nbsp;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  
> > &nbsp;&nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > &nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > &nbsp;&nbsp;&nbsp;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:
> 
> &nbsp;&nbsp;\<[http://rcrchive.net/rcr/show/321&gt](http://rcrchive.net/rcr/show/321&gt);
> 
> &nbsp;&nbsp;cut MyCut \< Firetruck  
> &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(options.merge(:nozzle =\> :big))  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> (Trans, can I omit the `MyCut \<' part?)
> 
> Cheers,  
> Daniel

I looked at that RCR a while back, but only glanced over it as it was not applicable to my situation at the time. Looking at it again, I see the beauty and power in it. I would love to see that end up in 2.0!

Tom

> **···**
>
> --  
> Tom Werner  
> Helmets to Hardhats  
> Software Developer  
> tom@helmetstohardhats.org  
> [www.helmetstohardhats.org](http://www.helmetstohardhats.org)

---

<div class="post-metadata">

**Author:** ![Tom\_Werner1](https://avatars.discourse-cdn.com/v4/letter/t/919ad9/32.png) [@Tom\_Werner1](https://rubytalk.org/u/Tom_Werner1)\
**Post date:** [14 July 2006 21:48 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/19 "2006-07-14T21:48:56Z")

</div>

dblack@wobblini.net wrote:

> Hi --
> 
> > Allow me to present a scenario:
> > 
> > class Firetruck  
> > &nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# code  
> > &nbsp;&nbsp;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  
> > &nbsp;&nbsp;alias\_method :\_\_old\_put\_out\_fire, :put\_out\_fire  
> > &nbsp;&nbsp;def put\_out\_fire(options = {})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_old\_put\_out\_fire(options.merge({:nozzle =\> :big}))  
> > &nbsp;&nbsp;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?
> 
> I don't know whether it qualifies as "monkeypatching" (I always  
> thought that meant doing something sloppy and ill-advised, which I  
> hope I'm not 🙂 but see if this helps:
> 
> &nbsp;&nbsp;class FireTruck  
> &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p options  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;FireTruck.class\_eval do  
> &nbsp;&nbsp;&nbsp;&nbsp;m = instance\_method(:put\_out\_fire)  
> &nbsp;&nbsp;&nbsp;&nbsp;define\_method(:put\_out\_fire) do |options|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.bind(self).call(options.merge({ :nozzle =\> "big" }))  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;FireTruck.new.put\_out\_fire(1 =\> 2)
> 
> &nbsp;&nbsp;# Now someone else uses the alias:  
> &nbsp;&nbsp;class FireTruck  
> &nbsp;&nbsp;&nbsp;&nbsp;alias old\_put\_out\_fire put\_out\_fire  
> &nbsp;&nbsp;&nbsp;&nbsp;def put\_out\_fire(options = {})  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "New version!"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;old\_put\_out\_fire(options)  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;FireTruck.new.put\_out\_fire(1 =\> 2)
> 
> Output:
> 
> {1=\>2, :nozzle=\>"big"}  
> New version!  
> {1=\>2, :nozzle=\>"big"}
> 
> David

This is a bit unrelated, but is there a way to give the block parameter of define\_method a default (because otherwise you now have to send put\_out\_fire at least an empty hash)?

define\_method(:put\_out\_fire) do |options|  
&nbsp;&nbsp;m.bind(self).call(options.merge({ :nozzle =\> "big" }))  
end

> **···**
>
> > On Fri, 14 Jul 2006, Tom Werner wrote:
> 
> --  
> Tom Werner  
> Helmets to Hardhats  
> Software Developer  
> tom@helmetstohardhats.org  
> [www.helmetstohardhats.org](http://www.helmetstohardhats.org)

---

<div class="post-metadata">

**Author:** ![\_Pena\_Botp1](https://avatars.discourse-cdn.com/v4/letter/_/94ad74/32.png) [@\_Pena\_Botp1](https://rubytalk.org/u/_Pena_Botp1)\
**Post date:** [14 July 2006 04:05 UTC](https://rubytalk.org/t/preferred-monkeypatching-technique/28947/20 "2006-07-14T04:05:19Z")

</div>

fr hal:  
# Actually it was only last week that I first saw this term  
# being used in the Ruby community. I wonder if it's too  
# late to squash it?

you took a vacation 😉  
[http://groups.google.com/group/comp.lang.ruby/browse\_thread/thread/9699d659bd806203](http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/9699d659bd806203)

kind regards -botp

[Next page](https://rubytalk.org/t/preferred-monkeypatching-technique/28947.md?page=2)
