Refinements. Am I doing Something wrong?

Hello everyone,

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?

Or am I doing something fundamentally wrong?

I used 2.0.0-rc1

Refinements were altered (pretty much at the last moment) to be file
scoped. So that’s why using only makes sense at toplevel.

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.

Just my $.02.

steve ross [email protected] wrote:

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.