Ruby Refinements: An Overview of a New Proposed Ruby Feature
Significant and serious improvements to the core Ruby language come along as infrequently as TextMate updates. Given that TextMate has had an update recently, an important new Ruby feature was sure to be just around the corner and it is: refinements! Shugo Maeda (who works with Matz and developer of mod_ruby) presented the idea at RubyConf 2010 last month.
In a nutshell, refinements clear up the messiness of Ruby's monkey patching abilities by letting you override methods within a specific context only. Magnus Holm has done a great write up of the concepts involved, and presents a good example:
module TimeExtensions refine Fixnum do def minutes; self * 60; end end end class MyApp using TimeExtensions def initialize p 2.minutes end end MyApp.new # => 120 p 2.minutes # => NoMethodError
In this example, rather than adding the
minutes method to the
Fixnum class in the typical way, it's been added as a "refinement" within a module which is then used elsewhere to spread the context of the change. Going a step further,
minutes could be defined on
Fixnum in many different ways within different classes and none of them would tread on each other's toes (or, at least, this could be mitigated).
Good for Rails?
Shortly after Magnus' explanation, Yehuda Katz stepped in with his own take in Ruby 2.0 Refinements in Practice - mostly focused around the impact refinements could have on Rails. Refinements seem particularly useful in the context of Rails considering how much monkeypatching ActiveSupport does in implementing methods like
days, and so forth.
Yehuda also looks at a situation where monkey patches in one library tread on the patches made in another library and how refinements could help clear things up.
Not so Good for Implementations?
Charles Oliver Nutter (of the JRuby team) also wrote up his take, and it's somewhat less positive. He argues that implementing refinements will reduce performance across the board and introduce several structural complexities, especially around the combination of runtime-mutable lexical scoping structures, concurrency, and method caching concerns.