Refinements – Ruby Monkey-Patching Redifined

refine String do def upcase self.downcase end end The above code defines a refinement. Now this is how you will be actually using it.

  class TestRefinement
    def modify_string
      test_string = “this Is A TesTSriNG”
      test_string.upcase  #will give “THIS IS A TESTSTRING”. Ruby default
    end
    using RefineString
    def testing_refinement
      test_string = “this Is A TesTSriNG”
      test_string.upcase  #will give “this is a teststring”. Refined
    end
  end
Looks weird, huh? What I did now is that I changed the default String::upcase function to down-case the string instead of up-casing it. Once you’re in the scope you need to use the refinement, call the using method with the module holding the monkey-patch/ monkey-patches (as they can hold more than one), you want to activate. At this scope, or any deeper scope, the refinement will be active. As of now, a using call affects all of the following scopes related to where it is called: The direct scope, such as the top-level of a script, the body of a class, or the body of a method or block Classes down-hierarchy from a refined class or module body Bodies of code run via eval forms that change the “self” of the code, such as module_eval Note that refinements applied in a class will be carried over to its subclasses. That means, if you are using my_refinements_module in your ParentClass, your ChildClass < ParentClass will have the refinements even if you don’t explicitly say using my_refinements_module your ChildClass. So, when using refinements, one must know everything about the calling hierarchy to foresee method calls and expected results. You can get the refinements version of ruby from the r29837 of trunk, and apply the patch. Here is how you do it using rvm.
  $ curl -O http://stuff.judofyr.net/refinements.diff
  $ rvm install ruby-head-r29837 –patch refinements.diff
  $ rvm ruby-head-r29837
monkey-patching has always been a risky prospect. It is scary that you will have to check for refinements before you inherit a class. So, if you are using one, make sure that its details are well documented along with your code. Monkey-patching is not encouraged to be used by a good programmer. But, refinement makes it less dangerous, and only ‘less’ dangerous.]]>