This week I got into a conversation regarding monkey-patching. For those
unfamiliar; a monkey-patch
is when you reopen a class outside of your project
and overwrite or add functionality to it. To give an example, here is a little
string monkey-patching goodness:
|
By reopening the String
class and adding an excited
method to it we are able
to add functionality to one of core classes that ships with Ruby, not to shabby.
Also note that it works for instances of String
that were created before the
monkey-patch took place.
Warning. Great care should be exercised when doing this. Because you are
changing classes that are outside of your control you’ll never know when updates
to them could introduce unforeseen bugs. To help minimize this impact and help
keep your code more modular I suggest using Ruby’s module
:
|
This has several benefits which will help save you headaches down the road.
- Because you are including a module you are guaranteeing that the class you are patching has been loaded first. It may not seem like a large problem; however, if you are overwriting functionality in a class this means your overwrites will be lost into the wind when the original class gets loaded.
- Relating to the first problem, if you simply use the
class
syntax to repoen a class and you are opening it for the first time, you can also run into a very obscure error ofsuperclass mismatch for class
. If the original class definition loads second and tries to use a parent class this is what happens.
|
- You are more prepared to move away from whatever it is you are patching.
Sometimes this isn’t possible, especially when you are patching a core class
like
String
. However; for some classes this is where you will want to head.
I hope this helps scratch the surface on monkey-patching and arms you with a bit better knowledge of how and why to do it. This is perhaps one of the greatest double-edged swords at your disposal. If you are working in a newer version of Ruby and are feeling froggy, I would also recommend looking at refinements.