What does 'Monkey Patching' exactly Mean in Ruby?

RubyTerminologyMonkeypatching

Ruby Problem Overview


According to Wikipedia, a monkey patch is:

> a way to extend or modify the runtime > code of dynamic languages [...] > without altering the original source > code.

The following statement from the same entry confused me:

> In Ruby, the term monkey patch was > misunderstood to mean any dynamic > modification to a class and is often > used as a synonym for dynamically > modifying any class at runtime.

I would like to know the exact meaning of monkey patching in Ruby. Is it doing something like the following, or is it something else?

class String
  def foo
    "foo"
  end
end

Ruby Solutions


Solution 1 - Ruby

The best explanation I heard for Monkey patching/Duck-punching is by Patrick Ewing in RailsConf 2007

> ...if it walks like a duck and talks like a duck, it’s a duck, right? So > if this duck is not giving you the noise that you want, you’ve got to > just punch that duck until it returns what you expect.

Solution 2 - Ruby

The short answer is that there is no "exact" meaning, because it's a novel term, and different folks use it differently. That much at least can be discerned from the Wikipedia article. There are some who insist that it only applies to "runtime" code (built-in classes, I suppose) while some would use it to refer to the run-time modification of any class.

Personally, I prefer the more inclusive definition. After all, if we were to use the term for modification of built-in classes only, how would we refer to the run-time modification of all the other classes? The important thing to me is that there's a difference between the source code and the actual running class.

> In Ruby, the term monkey patch was > misunderstood to mean any dynamic > modification to a class and is often > used as a synonym for dynamically > modifying any class at runtime.

The above statement asserts that the Ruby usage is incorrect - but terms evolve, and that's not always a bad thing.

Solution 3 - Ruby

Monkey patching is when you replace methods of a class at runtime (not adding new methods as others have described).

In addition to being a very un-obvious and difficult to debug way to change code, it doesn't scale; as more and more modules start monkey patching methods, the likelihood of the changes stomping each other grow.

Solution 4 - Ruby

This is monkey patching:

class Float
  def self.times(&block)
    self.to_i.times { |i| yield(i) }
    remainder = self - self.to_i
    yield(remainder) if remainder > 0.0
  end
end

Now I imagine this might be useful sometimes, but imagine if you saw routine.

def my_method(my_special_number)
  sum = 0
  my_special_number.times { |num| sum << some_val ** num }
  sum
end

And it breaks only occasionally when it gets called. To those paying attention you already know why, but imagine that you didn't know about the float type having a .times class-method and you automatically assumed that my_special_number is an integer. Every time the parameter is a whole number, integer or float, it would work fine (whole ints are passed back except when there is a floating-point remainder). But pass a number with anything in the decimal area in and it'll break for sure!

Just imagine how often this might happen with your gems, Rails plugins, and even by your own co-workers in your projects. If there's one or two little methods in there like this and it could take some time to find and correct.


If you wonder why it breaks, note that sum is an integer and a floating-point remainder could be passed back; in addition, the exponential sign only works when types are the same. So you might think it's fixed, because you converted bother numbers to floats ... only to find that the sum can't take the floating-point result.

Solution 5 - Ruby

You are correct; it's when you modify or extend an existing class rather than subclass it.

Solution 6 - Ruby

In Python monkeypatching is referred to a lot as a sign of embarrassment: "I had to monkeypatch this class because..." (I encountered it first when dealing with Zope, which the article mentions). It's used to say that it was necessary to take hold of an upstream class and fix it at runtime instead of lobbying to have the unwanted behaviors fixed in the actual class or fixing them in a subclass. In my experience Ruby people don't talk about monkeypatching that much, because it's not considered especially bad or even noteworthy (hence "duck punching"). Obviously you have to be careful about changing the return values of a method that will be used in other dependencies, but adding methods to a class the way that active_support and facets do is perfectly safe.

Update 10 years later: I would amend the last sentence to say "is relatively safe". Extending a core library class with new methods can lead to problems if somebody else gets the same idea and adds the same method with a different implementation or method signature, or if people confuse extended methods for core language functionality. Both cases often happen in Ruby (especially regarding active_support methods).

Solution 7 - Ruby

Explanation of the concept without code:

It means you can "dynamically" modify code. Wanna add a method "dynamically" to a particular class known only at "runtime"? No problem. It's powerful, yes: but can be misused. The concept "dynamically" might be a little too esoteric to understand, so I have prepared an example below (no code, I promise):

How to monkey patch a car:

Normal Car Operations

How do you normally start a car? It’s simple: you turn the ignition, the car starts!

Great, but how can we "monkey patch" the car class?

This is what Fabrizzio did to poor Michael Corleone. Normally, if you want to change how a car operates, you would have to make those changes in the car manufacturing plant (i.e. at "compile" time, within the Car class ^**). Fabrizzio ain't got no time for that: he monkey patches cars by getting under the bonnet to surreptitiously and sneakily rewire things. In other words, he re-opens the Car class, makes the changes he wants, and he's done: he's just monkey patched a car. he done this "dynamically".

You have to really know what you are doing when you monkey patch otherwise the results could be quite explosive.

> “Fabrizzio, where are you going?

Boom!

Monday, Tuesday, Wed-nes-day, Thursday, Friday, Sat-a-day. Image is free and open source from unsplash - https://unsplash.com/photos/dyrehVIidQk

Like Confucius Say:

> "Keep your source code close, but your monkey patches closer."

It can be dangerous.

^** yes i know, dynamic languages.

Solution 8 - Ruby

Usually it is meant about ad-hoc changes, using Ruby open classes, frequently with low quality code.

Good follow-up on the subject:

http://www.infoq.com/articles/ruby-open-classes-monkeypatching

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYaser SulaimanView Question on Stackoverflow
Solution 1 - RubyRSKView Answer on Stackoverflow
Solution 2 - RubyJoshua SwinkView Answer on Stackoverflow
Solution 3 - RubyAna BettsView Answer on Stackoverflow
Solution 4 - RubyRobert KView Answer on Stackoverflow
Solution 5 - Rubydavetron5000View Answer on Stackoverflow
Solution 6 - RubymethodView Answer on Stackoverflow
Solution 7 - RubyBenKoshyView Answer on Stackoverflow
Solution 8 - RubymaurycyView Answer on Stackoverflow