2017-01-25 2 views
1

SO ...Rubyでは、クラス変数を混​​合モジュールの動的に作成されたクラスメソッドに渡す方法は?

私はモジュールを持っている...

module Foo 
    class_methods do 
    def bar(*fields) 
     fields.each do |field| 
     define_method("set_#{field}=") do |value| 
      # nil check, other checks and validations 
     end 
    end 
    end 
end 

が...このモジュールは、自分のアプリケーションで私のモデルのいくつかで使用されますが、今のところ、私はそれをテストしようとしています...

let(:entity_type) do 
    class TestClass 
    def initialize(value) 
     @field_value = value 
    end 

    include Foo 
    bar @field_value 

    self 
    end 
end 

let(:entity) { entity_type.new(:some_field) } 

...しかし、私は私のテストでブレークポイントを入れて、エンティティのメソッドを見たとき、私は「SET_ =」の代わりに「set_some_field =」を参照してくださいと私はいくつかのバリエーションを試してみましたシンボル、クラスインスタンス変数などを使用しています。どんな助けも大歓迎です!

答えて

1

あなたのタイトルは「動的に作成されるクラスメソッド」ですが、インスタンスクラスを実際に動的に作成しているように見えます。つまり、それぞれ独自のset_x =メソッドのコレクションを持つTestClassのインスタンスを複数持つことができます。これは、あなたの望むことですか?

あなたがモジュールを作成することができ、そうと仮定:

module Foo 
    def bar(*fields) 
    fields.each do |field| 
     define_method("set_#{field}=") do |value| 
     # nil check, other checks and validations 
     end 
    end 
    end 
end 

をそしてそうのようなクラスを作成します。

class TestClass 
    extend Foo 
    def initialize(value) 
    @field_value = value 
    TestClass.bar(@field_value) 
    end 
end 

このようなこと:t = TestClass.new("boop")はメソッドset_boop=()であなたのインスタンスクラスtを与えるだろう。

別のインスタンスを作成する場合は、の前のインスタンスからのすべての新しいメソッドが追加されます。これは、各インスタンスでクラス定義を変更するためです。

この機能を使用したくない場合は、define_singleton_methodを使用して拡張するのではなくモジュールを含めることができます。これにより、他のインスタンスメソッドを作成するためのインスタンスメソッドbarが作成されます。あなたのクラスは、代わりに次のようになります:

module Foo 
    def bar(*fields) 
    fields.each do |field| 
     define_singleton_method("set_#{field}=") do |value| 
     # nil check, other checks and validations 
     end 
    end 
    end 
end 


class TestClass 
    include Foo 
    def initialize(value) 
    @field_value = value 
    bar(@field_value) 
    end 
end 

これはあなたが探しているものではない場合は私に教えて、私は私の答えを変更します。

+0

優れた答え。 –

関連する問題