includeしたmoduleのconst_missingが実行されるようにする。
昨日の続き。includeしたmoduleのconst_missingは実行されないわけですが、ふと思い立って以下のコードを試してみたら無事動作しました。戦略的には、
- includeしたクラスでconst_missingを定義しておき、
- その中で、includeしたモジュールから定義を探す。
というものです。
module A AAA = "AAA" def self.const_missing(id) return "BBB" if id == :BBB raise "not found." end end puts A::AAA puts A::BBB class X include A def hoge puts AAA puts BBB end #未定義の定数が参照された場合呼び出される def self.const_missing(id) #includeしているモジュールから順に探索する。 included_modules.each {|m| begin return m.const_get(id) rescue NameError end } #どれにも定義されていなければエラー raise NameError.new end end X.new.hoge
実行結果です。
AAA BBB AAA BBB
さて、これで一応const_missingが呼び出されるようにはなりましたが、include先クラスでいちいちメソッドを定義するのはあまりにもしんどい。ということで、moduleに以下のメソッドを追加。
class Module #プロキシモジュールをincludeする。 def include_proxy( mod ) include mod class << self def const_missing(id) self.included_modules.each {|m| begin return m.const_get(id) rescue NameError end } raise NameError.new end end end end
これで、最初のコードは以下のとおり書けるようになります。
module A AAA = "AAA" def self.const_missing(id) return "BBB" if id == :BBB raise "not found." end end puts A::AAA puts A::BBB class X include_proxy A def hoge puts AAA puts BBB end end X.new.hoge
実行結果です。
AAA BBB AAA BBB