I was pretty interested in refinements
in Ruby 2.0, and after listening to the latest Ruby Rouges podcast where some serious doubts were raised about the viability of refinements I thought I’d build a little example of how I was thinking I could use it.
I failed first time out and I tried copying and pasting examples without success. After some time poking around I found a blog post about why this wasn’t working. Ultimately, refinements are sort of left in the language, but not fully supported and are marked as experimental.
Here’s what I wanted to achieve. Coming from Scala in my previous job, I thought I could use refinements as a proxy for implicit conversions. Here I refine the Fixnum class to allow it to respond to a to_currency
message. When called it converts the Fixnum instance to a Currency instance.
class Currency
attr_reader :units
def initialize units
@units = units
end
end
module CurrencyExtensions
refine Fixnum do
def to_currency
Currency.new(self)
end
end
end
class App
using CurrencyExtensions
def initialize
puts 3.to_currency
end
end
App.new
Why is this interesting to me? Well, I think being able to write 3.to_currency
can result in nicer to read code than the alternative Currency.new(3)
. Small difference perhaps.
There is a way to get this to work by having the using
keyword in the global context, but it doesn’t deliver the full impact I was hoping for.
class Currency
attr_reader :units
def initialize units
@units = units
end
end
module CurrencyExtensions
refine Fixnum do
def to_currency
Currency.new(self)
end
end
end
using CurrencyExtensions
puts 3.to_currency
I’ve got other ideas to build upon this if it ever makes it into the full specification. I’ll keep watching for now.