Issue #9580 has been updated by Shugo Maeda.


David Albert wrote:
> This seems like a bug because the code behaves differently in IRB than how it behaves in the file. If it's the intended behavior, it's frustrating because it makes it harder to prototype code that uses refinements in the REPL.

This change was intentionally introduced in r42396.
The following code illustrates why using doesn't work on IRB.

```ruby
module Foo
  refine Object do
    def foo
      puts "foo"
    end
  end
end

eval("using Foo; foo") # Foo is activated only in the given string
eval("foo")       # => NoMethodError
```

I understand it's not convenient for prototyping.
How about to add a new option for using to activate refinements globally?

```ruby
eval("using Foo, global: true")
eval("foo") #=> foo
```


----------------------------------------
Bug #9580: Refinements regression in IRB
https://bugs.ruby-lang.org/issues/9580#change-45527

* Author: David Albert
* Status: Open
* Priority: Normal
* Assignee: 
* Category: 
* Target version: 
* ruby -v: 2.2.0dev
* Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
The problem: Top level refinements do not work in IRB. They worked in 2.0.0-p451, but don't work in 2.1.0, 2.1.1, or today's trunk.

Details:

Here some code in a file:

    #refine.rb
    
    module A
      refine String do
        def asdf
          :asdf
        end
      end
    end
    
    using A
    
    p "foo".asdf
    
In all versions, of Ruby between 2.0.0-p451 and 2.2.0dev, running this file, prints `:asdf`. This is the expected behavior. Ruby 2.0.0 also prints the "Refinements are experimental" warning, as expected:

    # Ruby 2.0.0-p451
    $ ruby refine.rb 
    refine.rb:2: warning: Refinements are experimental, and the behavior may change in future versions of Ruby!
    :asdf

    # Ruby 2.1.0, 2.1.1, and 2.2.0dev
    $ ruby refine.rb 
    :asdf


In Ruby 2.0.0-p451, the same code also works in IRB, also as expected:

    irb(main):001:0> "#{RUBY_VERSION}-#{RUBY_PATCHLEVEL}"
    => "2.0.0-451"
    irb(main):002:0> module A
    irb(main):003:1>   refine String do
    irb(main):004:2*     def asdf
    irb(main):005:3>       :asdf
    irb(main):006:3>     end
    irb(main):007:2>   end
    irb(main):008:1> end
    (irb):3: warning: Refinements are experimental, and the behavior may change in future versions of Ruby!
    => #<refinement:String@A>
    irb(main):009:0> using A
    => main
    irb(main):010:0> "foo".asdf
    => :asdf

However, in all newer versions of Ruby (2.1.0, 2.1.1, and 2.2.0dev), this code raises a `NoMethodError` in IRB:

    irb(main):001:0> RUBY_VERSION
    => "2.1.0"
    irb(main):002:0> module A
    irb(main):003:1>   refine String do
    irb(main):004:2*     def asdf
    irb(main):005:3>       :asdf
    irb(main):006:3>     end
    irb(main):007:2>   end
    irb(main):008:1> end
    => #<refinement:String@A>
    irb(main):009:0> using A
    => main
    irb(main):010:0> "foo".asdf
    NoMethodError: undefined method `asdf' for "foo":String
    	from (irb):10
    	from out/bin/irb:11:in `<main>'


    irb(main):001:0> RUBY_VERSION
    => "2.1.1"
    irb(main):002:0> module A
    irb(main):003:1>   refine String do
    irb(main):004:2*     def asdf
    irb(main):005:3>       :asdf
    irb(main):006:3>     end
    irb(main):007:2>   end
    irb(main):008:1> end
    => #<refinement:String@A>
    irb(main):009:0> using A
    => main
    irb(main):010:0> "foo".asdf
    NoMethodError: undefined method `asdf' for "foo":String
    	from (irb):10
    	from bin/irb:11:in `<main>'


    irb(main):001:0> RUBY_VERSION
    => "2.2.0"
    irb(main):002:0> module A
    irb(main):003:1>   refine String do
    irb(main):004:2*     def asdf
    irb(main):005:3>       :asdf
    irb(main):006:3>     end
    irb(main):007:2>   end
    irb(main):008:1> end
    => #<refinement:String@A>
    irb(main):009:0> using A
    => main
    irb(main):010:0> "foo".asdf
    NoMethodError: undefined method `asdf' for "foo":String
    	from (irb):10
    	from bin/irb:11:in `<main>'

This seems like a bug because the code behaves differently in IRB than how it behaves in the file. If it's the intended behavior, it's frustrating because it makes it harder to prototype code that uses refinements in the REPL.

This issue is not specific to IRB. I get the same behavior in Pry (works in 2.0.0, doesn't work in newer Ruby versions). This makes me think the issue is not inside the IRB source, but rather has something to do with `using`'s behavior in the `Binding` objects that IRB and Pry are probably using. I haven't looked at the Pry or IRB source in quite a long time, so this paragraph is mostly speculation.

Please let me know if there's any more info I can provide to make this easier to fix



-- 
http://bugs.ruby-lang.org/