From: Yehuda Katz Date: 2011-12-20T02:03:34+09:00 Subject: [ruby-core:41726] [ruby-trunk - Bug #5777] class_eval/module_eval works differently when given a string than when given a block in 1.9.2 and 1.9.3 Issue #5777 has been updated by Yehuda Katz. It's important to note that most uses of class_eval with a block are mostly taking existing blocks and modifying their context. For example, take a look at the rspec DSL: describe "TrueClass" do it "should not be initializable" do lambda { TrueClass.new }.should raise_error(NoMethodError) end end Intuitively, users expect this TrueClass to be looked up in the context of the original block, not in the context of the eval. The POLS argument only makes sense in a very synthetic environment where users are the ones making most of the calls to class_eval, when in fact most calls are made *on behalf of users*. There was a change in 1.9.x series along the lines of what you are suggested, and it caused serious problems for all kinds of libraries. It was reverted in 1.9.2 once the mayhem became obvious. ---------------------------------------- Bug #5777: class_eval/module_eval works differently when given a string than when given a block in 1.9.2 and 1.9.3 https://bugs.ruby-lang.org/issues/5777 Author: George MacKerron Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.1] class_eval/module_eval works differently when passed code as a string than when passed the same code as a block in 1.9.2/1.9.3. In particular, constant lookup appears to vary. Here's a very short test case (this is on a Mac on 1.9.2, but I see the same behaviour on Ubuntu and on 1.9.3p0): dyn200:~ George$ ruby -v ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.1] dyn200:~ George$ irb irb(main):001:0> class A; X = 1; end; A.class_eval 'X' => 1 irb(main):002:0> class B; Y = 1; end; B.class_eval { Y } NameError: uninitialized constant Class::Y from (irb):2:in `block in irb_binding' from (irb):2:in `class_eval' from (irb):2 from /Users/George/.rbenv/versions/1.9.2-p290/bin/irb:12:in `
' It appears this was not the case in 1.9.1: george@production:~$ ruby -v ruby 1.9.1p378 (2010-01-10 revision 26273) [i486-linux] george@production:~$ irb irb(main):001:0> class A; X = 1; end; A.class_eval 'X' => 1 irb(main):002:0> class B; Y = 1; end; B.class_eval { Y } => 1 It seems unlikely this in intentional (?) -- it certainly violated 'least surprise' for me! I note also that with const_get it works OK either way, including with a block: irb(main):001:0> class B; Y = 1; end; B.class_eval { const_get :Y } => 1 -- http://redmine.ruby-lang.org