3

取り決めは次のとおりです。クラス Box の特定のインスタンスをいくつかのメソッドで拡張する必要があります。モジュール内にライブを含める必要があるメソッドと、Box インスタンスにモジュールを動的に含めることができるようにしたい。今、私はevalでフックを使用しています:

class Box
  def after_initialize
    if self.injected_module.present?
      eval("class << self; include #{self.injected_module}; end")
    end
  end
end

それは非常にうまく機能していますが、evalを使用すると本当に汚いと感じます。私はそのようなものを探しています:

module_to_inject = self.injected_module
self.eigenclass.class_eval do
   include module_to_inject
end

しかし、次のようにクラスにモンキーパッチを適用しないと、固有クラスにclass_evalを実行させることができません。

class Box; def eigenclass; class << self; self; end end end

これを行うための美しい(そして信頼できる)方法はありますか?

4

2 に答える 2

8

モジュールからBox動的の特定のインスタンスにメソッドを追加するために必要なのは、Kernel#extendメソッドだけです。

box.extend MyModule

また、「注入する」という動詞は、Ruby ではすでに意味を持っているEnumerable#injectため、これを説明するのに最適な動詞は「拡張する」です。

于 2011-03-14T05:56:06.253 に答える
3

私はそこにあなたの推論に従うことができません. self.class.class_eval次のように、あなたの例では問題なく動作します。

class Box
  def after_initialize
    self.class.class_eval do
      include(self.injected_module)
    end
  end
end

編集:コメントを明確にします。

次のように、クラス メソッドとしてモジュールにメソッドを含めるために使用Object#extendします (固有クラスで定義するのと同じように)。

module MyModule
    def method
        puts "called from #{self.inspect}"
    end
end

class Box
    def self.injected_module
        MyModule
    end

    def require_module
        self.class.class_eval do
            extend self.injected_module
        end
    end
end

b = Box.new
b.require_module
Box.method
# prints "called from Box"
于 2011-03-14T02:20:40.953 に答える