How not to cut your source with sharp knife as Monkey Patch in Ruby

March 13, 2017

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

Actually, you can reopen any class and change how it works. This includes the default Ruby classes like String, Array or Hash. It sounds extremely challenging. Being able to change the expected outcome of a method can cause all sorts of weird behavior and difficult to track down bugs. Monkey Patch to help. In Ruby, the term monkey patch(MP) mean any dynamic modification to a class and is often used as a synonym for dynamically modifying any class (add new or overwrite existing methods) at runtime.

As you see, Ruby is like a sharp knife, it can be extremely effective, but it’s usually your own fault if you cut yourself. Let me explain. On the one hand, there are some disadvantages working with such sharp knife.

When you monkey patch a class (disadvantages):

If two libraries monkey-patch the same method, the first monkey-patch will get overwritten and disappear forever.

If there’s an error, it’ll look like the error happened inside the class.

Instead, you could put your monkey patches in a module, but both variants have the same problem: the patch is globally and your changes could unexpectedly be overwritten by the third library.

On the other hand, the MP is a pretty powerful instrument in right hands and you are free to use it. Only need to remember that abuse the patching can easy to introduce bugs and make the debugging very difficult.

In case you only need the different behavior in a few specific places and not throughout the whole system, you can use Refinements. Refinements are a mechanism to add new or redefine existing methods the behavior of an object in a limited and controlled way.
How to use Refinements?

Is it ok to Monkey Patch?

Actually, there are some cases where reopening a class does make sense. And there are many cases where it’s fine to Monkey Patch, but it should definitely not be your first weapon of choice.
Monkey patching allows you to come up with a "quick and dirty" solution to a problem, but you should use it very sparingly. Refinements are a way to limit the scope of an extension to a class to only the code we control.
Enjoy your code!