Refinements: Fancy Monkey-patching

Top hat, monocle and sweet stashA common gripe I’ve heard people bring up about Ruby is the fact that you can monkey-patch basically anything at any point during runtime. The result is that the world your code expects could potentially change under it and all hell breaks loose.  What if you included a 3rd party library that changed your expectations of .to_s?

Here’s a contrived example:

There is another way to monkey-patch that is safer — refinements!  Refinements have been in Ruby since 2.0 and essentially provides a way to namespace your monkey-patching efforts.

Creating and using refinements is pretty easy and requires:

  1. Create a module to hold your refinements
  2. USE that module inside your code

When making use of refinements the changes are scoped/limited within the scope of the module using said refinements. Here’s an example:

First we can create a module to hold our changes to the Integer class:

Next, via using, we can “use” this refinement in our own code!

Now finally here’s an example of calling CrazyInteger and how using refinements has protected Integer#to_s outside of the scope of CrazyInteger‘s class.