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.
About the Author