cult3

What is Monkey Patching in Ruby?

Jun 17, 2015

Table of contents:

  1. What is an example of Monkey Patching?
  2. When should you use Monkey Patching?
  3. When is it ok to Monkey Patch?

One of the most powerful aspects of Ruby is the ability to re-open any class and change it’s methods.

Yes that’s right, you can actually reopen any class and change how it works. This includes the standard Ruby classes like String, Array or Hash!

Now this is obviously as dangerous as it sounds. Being able to change the expected outcome of a method can cause all sorts of weird behaviour and difficult to track down bugs.

But nonetheless, the ability to “Monkey Patch” any class is extremely powerful. Ruby is like a sharp knife, it can be extremely effective, but it’s usually your own fault if you cut yourself.

In today’s tutorial we’ll be looking at Monkey Patching in Ruby.

What is an example of Monkey Patching?

To illustrate Monkey Patching we’ll make some changes to the good old String core class.

First up, we’ll add a handy method to generate some Lorem Ipsum text:

class String
  def self.lipsum
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
  end
end

In this example I’ve reopened the String core class and added a lipsum Class Method (Understanding Class Methods verses Instance Methods in Ruby).

You can now use this method on the String class like this:

String.lipsum
# => "Lorem ipsum dolor sit amet, consectetur adipiscing elit."

However, not only can we added methods to the core String class, we can also modify the behaviour of existing methods!

class String
  def upcase
    self.reverse
  end
end

In this example we’re hijacking the upcase method and calling the reverse method instead!

'hello'.upcase
# => "olleh"

So as you can see, it’s incredibly easy to add or modify methods on an existing class, even when you don’t own that class or it is part of the core of Ruby.

When should you use Monkey Patching?

Rarely.

Ruby provides us with a wealth of powerful tools to work with. However, just because a tool is powerful, does not make it the right tool for the job.

Monkey Patching in particular is an extremely powerful tool. However, a powerful tool in the wrong hands will cause endless amounts of pain and suffering.

Whenever you Monkey Patch a class you are potentially creating a headache at some point in the future when things go wrong.

Classes that have been Monkey Patched are more difficult to understand and debug. If you’re not careful, the error message you will receive will likely give you very little clue as to what the problem actually is.

When you Monkey Patch a method you will potentially be breaking code downstream that is relying on that behaviour.

When you add a new method to an existing class using Monkey Patching you are potentially opening weird edge cases that you can’t possible foresee.

When is it ok to Monkey Patch?

Now with that being said, there’s no point in having powerful tools like Monkey Patching if you don’t actually make use of them.

There are cases where reopening a class does make sense.

For example, you often see Monkey Patches that simply add a convenience method that has no side effect. Ruby has a very beautiful syntax and so it can be tempting to Monkey Patch a class to turn some ugly method call into something that is more readable.

Or perhaps you need to Monkey Patch a class you own.

There are many cases where it’s fine to Monkey Patch, but it should definitely not be your first weapon of choice.

It will often be the case that Monkey Patching is just the lazy developer’s preference over actually refactoring or implementing a known design pattern for a particular problem.

Just because Monkey Patching offers you an easy solution, does not mean that you should always take that path.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.