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.
