From: hanachin@... Date: 2015-02-03T07:27:26+00:00 Subject: [ruby-core:67972] [ruby-trunk - Bug #10818] Extrange behaviour when apliying a refinement inside eval 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 `
' ``` 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 `
': undefined method `bar' for # (NoMethodError) # from refinement.rb:13:in `eval' # from refinement.rb:13:in `
' # # actual 2.2.0 # refinement.rb:11:in `
': undefined method `bar' for # (NoMethodError) # from refinement.rb:13:in `eval' # from refinement.rb:13:in `
' ``` ---------------------------------------- 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 = <