I am currently playing around with Ruby 2.0. I wanted to look into
Refinements and here is what I came up with:
====
module RefinementTest
refine Hash do
def super_duper
“Hello World”
end
end
end
class MyTestClass
using RefinementTest
def initialize
puts {}.super_duper
end
end
MyTestClass.new
This is basically how it’s described everywhere.
However when I run this code, I’ll get that error:
====
[~]$ ruby refinements.rb
refinements.rb:2: warning: Refinements are experimental, and the
behavior may change in future versions of Ruby!
refinements.rb:10:in <class:MyTestClass>': undefined methodusing’ for
MyTestClass:Class (NoMethodError)
from refinements.rb:9:in `’
It only works when I move the ‘using RefinementTest’ one level up (in
the main namespace). But isn’t that the same as monkeypatching the Hash
class in the first place?
This is kind of a bummer. I have a gem that I’d like not to make
dependent on some other arbitrary gem(s). (Yes, I know rubygems is a
dependency manager.) In any case, to avoid pulling in all of
ActiveSupport, I implement my own flavor of Inflector. And I put a few
keen methods on String like String.singularize and String.pluralize…
All well and good until some other library with some other
implementation of these String extensions gets pulled in.
So using what I thought refinements would be, I could have done:
module CoreExtensions
class String
def singularize
# something here
end
end
end
class MyConsumerClass
using CoreExtensions
def do_something
puts “dogs”.singularize
end
end
This would magically have scoped my String extensions to the
CoreExtensions module, preventing any namespace pollution, while at the
same time allowing include-like access to these extensions within my
class.
File scope is ok, but nowhere near as precise as module or class scoped
refinements.
end
This would magically have scoped my String extensions to the
CoreExtensions module, preventing any namespace pollution, while at the
same time allowing include-like access to these extensions within my
class.
But you can still do that:
module CoreExtensions
refine String do
def singularize
“howdy”
end
end
end
using CoreExtensions
class MyConsumerClass
def do_something
puts “dogs”.singularize
end
end
MyConsumerClass.new.do_something
That works because MyConsumerClass was defined after the “using”
statement, so it gets the refinement of String. Nothing else does. “Some
other library with some other implementation” does not.
I missed the earlier discussion on this thread, though, so perhaps this
isn’t helpful…
m.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.