2012-03-03 16 views
0

新しいアクセサを作成していて、情報を保持する独自の配列変数を持っていますが、そのメソッドでclass_evalを呼び出そうとすると、その変数のプッシュメソッドは機能しません。ルビ配列にプッシュできません

そのクラスで記述された方法と、次のようにclass_evalメソッド行が読み:

class_eval "def #{attr_name}=(value); #{attr_name} = value; #{information}.push value; end; def #{attr_name}_history; #{information}; end" 

ので、この行のプッシュが動作しません。

答えて

0

class_evalを呼び出すときにローカル変数informationによって格納されている文字列は、実際にこの関数を追加するクラスのメソッドであることを確認する必要があります。

私はクラスにhistoryメソッドがあることを確認しているので、次のように動作します。

class A 
    def history 
    @history ||= [] 
    end 
end 

attr_name = "foo" 
information = "history" 
A.class_eval "def #{attr_name}=(value); #{attr_name} = value; #{information}.push value; end; def #{attr_name}_history; #{information}; end" 

a = A.new 
a.foo = "bar" 
a.foo = "baz" 
a.foo_history 
+0

また、a.barとa.otherなどがある場合はどうなりますか?これらの変数の別々のコピーを保持しますか? – eytanfb

+0

この例では、 'attr_name'は' class_eval'が実行される前に '' foo ''と評価されるので、1つのパラメータの履歴だけが追加されます。あなたが言及するすべての変数に対してこのロジックを実行するmixinを書くこともできますし、instance_variablesを調べて自動的に追加することもできます。 –

0

「#{情報が}」informationストリング値ではなく、実際の配列オブジェクト自体が返されるので、それは動作しません。これは、作成時に文字列の代わりに使用されるためです。

あなたが作業しているオブジェクトのスコープと作業しているクラスの両方に含まれる変数に変更する必要があります。例えば、のようなものにそれを変更してみてください:

Foo::Information = [...] 
class_eval " 
    class_eval " 
    def #{attr_name}=(value) 
    #{attr_name} = value 
    Foo::Information.push value 
    end 
    def #{attr_name}_history 
    Foo::Information 
    end" 
    " 
0

これはinformation変数が配列として初期化されなければならないので、あなたがそれにpushメソッドを呼び出すことができます。このような何か:あなたは二回次の時間を考えなければならないので、

def #{attr_name}=(value); 
    #{attr_name} = value; 
    (#{information}||=[]).push value; 
end; 
def #{attr_name}_history; 
    #{information}; 
end 

ところで、あなたの整形は、醜いです。

+0

私はそれを複数行にしようとしていましたが、%QをIDE上で動作させることができませんでした。 – eytanfb

関連する問題