この記事はOkinawa.rb Advent Calendar 2018の16日目の記事です。
class_eval の中で定数を定義したときのスコープですが、オープンクラスしたときと違ってブロックの外側のスコープで定義されます。
class_eval {|mod| ... } -> object
ブロックが与えられた場合には、定数とクラス変数のスコープはブロックの外側のスコープになります。
https://docs.ruby-lang.org/ja/2.5.0/method/Module/i/class_eval.html
オープンクラスの場合
class Foo
end
class Foo
BAR = 'baz'
end
puts Foo::BAR
$ ruby foo.rb
baz
class_eval の場合
class Foo
end
Foo.class_eval do
BAR = 'baz'
end
puts Foo::BAR
Ruby 2.4 までは警告が出るものの実行できます。
$ ruby foo.rb
foo.rb:8: warning: toplevel constant BAR referenced by Foo::BAR
baz
Ruby 2.5 以上だとエラーになります。
Ruby 2.5.0 リリース
トップレベルの定数検索は削除されました。[Feature #11547]
https://www.ruby-lang.org/ja/news/2017/12/25/ruby-2-5-0-released/
$ ruby foo.rb
Traceback (most recent call last):
vending_machine2.rb:8:in `<main>': uninitialized constant Foo::BAR (NameError)
Did you mean? BAR