Issue #10818 has been updated by Seiei Higa.


The `Kernel.#eval` behaves like:

``` ruby
eval('a = 42')
eval('p a')
# bar.rb:2:in `eval': undefined local variable or method `a' for main:Object (NameError)
#   from bar.rb:2:in `eval'
#   from bar.rb:2:in `<main>'
```

But `Binding#eval` behaves like:

``` ruby
b = binding
b.eval("a = 42")
b.eval("p a")
# => 42
```

So, I expect following code works fine, but it raises `NoMethodError` in ruby 2.1.5, 2.2.0

``` ruby
class Foo; end

module M
  refine(Foo) do
    def bar
      42
    end
  end
end

b = binding
b.eval('using M')
puts b.eval('Foo.new.bar')

# expected:
#   42
#
# actual 2.0.0:
#   refinement.rb:4: warning: Refinements are experimental, and the behavior may change in future versions of Ruby!
#   42
#
# actual 2.1.5:
#   refinement.rb:11:in `<main>': undefined method `bar' for #<Foo:0x007fe3040fd568> (NoMethodError)
#     from refinement.rb:13:in `eval'
#     from refinement.rb:13:in `<main>'
#
# actual 2.2.0
#   refinement.rb:11:in `<main>': undefined method `bar' for #<Foo:0x007f9fba04e488> (NoMethodError)
#     from refinement.rb:13:in `eval'
#     from refinement.rb:13:in `<main>'
```

----------------------------------------
Bug #10818: Extrange behaviour when apliying a refinement inside eval
https://bugs.ruby-lang.org/issues/10818#change-51359

* Author: Pablo Herrero
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-linux]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
When you activate a refinement inside an a string using `eval` with a binding, the refinement is sill active the next time you call `eval` with the same binding.
Strangely enough, this will only happen if there is an assignment at the code evaluated the first time. If you delete the assignment everything works as expected.

```ruby
module M
  refine String do
    def foobar; puts 'foobar'; end
  end
end

some_binding = class A; binding; end


str1 = <<EOF
a = 'something' # Without this everything works as expected
using M
'str'.foobar # Works fine
EOF

str2 = <<EOF
'str'.foobar # This time should fail but it doesn't
EOF

eval str1, some_binding
eval str2, some_binding
```

Acording to the [RefinmentsSpec](https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec): "when main.using is invoked in a string given as the first argument of Kernel#eval, Kernel#instance_eval, or Module#module_eval, the end of the scope is the end of the string."

Which contradicts with this code's behavior.



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