af83

Ruby 2.0 : Module#refine

We already talked about Module#prepend as one of the new features of the upcoming Ruby 2.0… Today, let's talk about refinements. Refinements had landed into trunk, but is actually reviewed. It could eventually be reverted for performance issues.

Why refinements

Because Monkey patching: Monkey patching is a powerful feature, but as everybody knows, with great power comes great responsibility. Refinements intend to give you the power of Monkey patching, but without messing with the whole universe of the Ruby runtime.

Module#refine

module FooBar
  refine String do
    def hello
      puts "#{self} says : Hello, world"
    end
  end
end

class Bar
  using FooBar
  attr_reader :user

  def initialize(user)
    @user = user
  end

  def say
    user.hello
  end
end

Bar.new('af83').say
String.new.say

In the module FooBar, we use the class method refine to enhance the class String. And in the class Bar, we declare that we want to use FooBar with the using methods.

Running this code with Ruby 2.0 outputs the following:

af83 says : Hello, world
refinements.rb:23:in `<main>': undefined method `say' for "":String (NoMethodError)`'`

What's happening here

When we call Bar.new('af83').say, the addition of the method hello on the class String is only effective in the context of the Bar class, thanks to the use of using FooBar.

On the contrary, String.new has no knowledge of the method say. Hence, the NoMethodError.

Like I said, safer monkey patching. :)

Resource

You can read the whole story of refinements in Ruby.

Coming next in this series: Enumerator::Lazy.

blog comments powered by Disqus