What is a monkey patch (Monkey Patch)? In dynamic languages, you append and change functionality without modifying the source code.
The purpose of using monkey patches:
1. Additional function
2. Function change
3. Error correction procedure
4, increase the hook, in the execution of a method while performing some other processing, such as printing logs, to achieve AOP, etc.
5, the cache, in the calculation is very large, the results of the settlement can be used repeatedly, after the completion of a calculation, to replace the method can improve the processing speed.
Ruby's classes are open classes that can be added arbitrarily after the class definition, making it particularly easy to use monkey patches in Ruby. In addition, Ruby provides the ability to operate on methods, classes, and modules, allowing us to use monkey patches more handy. The basic features that Ruby provides are as follows:
Alias: Alias to Method
Include: ways to introduce other modules
Remove_method: Canceling methods in this class
Undef: Cancel method
using monkey Patch in Ruby
The scene I came across was this:
We use the third party library fog for EC2 operation. Many commands, such as creating an instance, need to set this argument for the instance type. In fog, all types of EC2 are defined in the FOG/AWS/MODELS/COMPUTE/FLAVORS.RB flavors array. If the type being set is not in the flavors array, the fog will be treated as an invalid argument.
Later, Amazon released a new instance type D2. Although Ruby's third-party community is very active, the fog development community is not adding D2 to flavors.rb in time, and our work is in dire need of D2-type examples.
The background is complete, then see what kind of solution.
Method One: We can submit a Pull Request to fog to add a new type.
But this method is not workable. The knife-ec2 we use for fog must be 1.25.*, but fog has been updated to 1.31.0, and fog has changed significantly from the start of the 1.27.0 structure. Obviously, we cannot wait for KNIFE-EC2 upgrades to support the new version of fog, so we submit Pull Request update fog does not solve the problem.
Method Two: Manually update the old version fog since the latest version of the fog, we can manually edit the version 1.25 of the fog, and then packaged into a Gem to use. This method is easier to operate than the previous one, but it is not easy to maintain when it comes to problems. For a minimal change, adding your own code to a Third-party library is always a "clean" one.
Finally, under the guidance of colleagues, I adopted a third method, namely Monkey Patch. I added a file lib/project_name/monkey_patches/flavors.rb to our Ruby project and then added the following code to the file to modify the Fog/aws/models/compute/flavors:
Require ' fog/aws/models/compute/flavors '
class Object
def redef_without_warning (const, value)
mod = Self.is_a? (Module)? Self:self.class
mod.send (: remove_const, const) if mod.const_defined? CONST)
mod.const_set (const, value) End-end
module Fog
module Compute
class AWS
New_ flavors = flavors + [
{
: id => ' d2.xlarge ',
...
},
{
: id => ' D2.2xlarge '
...
},
{
: id => "D2.4xlarge",
...
},
{
: id => "D2.8xlarge",
...
}
]
redef_without_warning:flavors, New_flavors end end
Summarize
by adding a monkey patch to your code, we have successfully implemented the dynamic addition of the new instance type to the fog. We can finally use fog to create D2 type of machine, and this method changes the amount of code is minimal, and easier to maintain.
Monkey Patch is not the perfect solution, it will introduce some traps. So this technique has some controversy in the field of software engineering. However, I still think that Monkey Patch is a good zero-sex solution.