2012-03-03 69 views
0

我正在寫一個新的存取器,它有它自己的數組變量來保存信息,但是當我嘗試在其方法中調用class_eval時,該變量上的push方法不起作用。不能推入紅寶石陣列

及其寫入級和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.another等,該怎麼辦。這會保留這些變量的單獨副本 – eytanfb 2012-03-03 21:09:53

+0

在此示例中,'attr_name'在執行'class_eval'之前計算爲「foo」,因此它只爲一個參數添加歷史記錄。你可以編寫一個mixin爲你提到的每個變量運行這個邏輯,或者甚至查看instance_variables並自動添加它。 – 2012-03-05 03:52:15

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 2012-03-03 21:00:49