挙動を修正したパッチを書いてみました。
ただ、意図的にそのような実装にしていた節があるのでこれが仕様なのかバグなのかは現時点で判断するのはちょっとむずかしそうですね。
該当箇所を消してもテストはパスしていたんですが…。
わたしも処理に一貫性を持たせるためには true を返したほうがいいと思います。
また、元々は以下の issues で議論されていたようです。
- Feature #7414: Now that const_get supports
Foo::Bar; syntax, so should const_defined?. - Ruby trunk - Ruby Issue Tracking System
修正前¶
module M
HOGE = 42
end
class X
include M
end
# OK: 問題なく取得できる
p X.const_get("HOGE") # => 42
p Object.const_get("X::HOGE") # => 42
# OK: 期待する値が返ってくる
p X.const_defined?("HOGE") # => true
# NG: const_get で値は取得できるが false が返ってくる
p Object.const_defined?("X::HOGE") # => false
修正後¶
module M
HOGE = 42
end
class X
include M
end
# OK: 問題なく取得できる
p X.const_get("HOGE") # => 42
p Object.const_get("X::HOGE") # => 42
# OK: 期待する値が返ってくる
p X.const_defined?("HOGE") # => true
# OK: true が返ってくる
p Object.const_defined?("X::HOGE") # => true
# OK: 第二引数に false を渡すと mixin が考慮されないようになるので false になる
p Object.const_defined?("X::HOGE", false) # => false
ユースケース¶
定数が存在しない場合に動的に mixin を行いたい場合は include が考慮されていてほしい。
module Valuable
VALUE = 42
end
class X
end
def get
# 遅延して mixin する
if !Object.const_defined?("X::VALUE")
pp "homu"
X.include Valuable
end
Object.const_get("X::VALUE")
end
# 最初のメソッド呼び出しでのみ mixin したい
p get
p get
p get