Forum: Ruby Refinements. Am I doing Something wrong?

Posted by Leif Gensert (leifg)
on 2013-01-11 00:26
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 method `using' for
MyTestClass:Class (NoMethodError)
        from refinements.rb:9:in `<main>'
====

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
Posted by Thomas Sawyer (7rans)
on 2013-01-11 02:14
(Received via mailing list)
Refinements were altered (pretty much at the last moment) to be *file*
scoped. So that's why `using` only makes sense at toplevel.
Posted by Steve Ross (cwd)
on 2013-03-06 23:22
(Received via mailing list)
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.
Posted by Matt Neuburg (Guest)
on 2013-03-07 17:56
(Received via mailing list)
steve ross <cwdinfo@gmail.com> 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.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.