読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

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