2012-10-09 74 views
1

可能重複添加@variables到現有的 '初始化' 的方法:
Ruby.Metaprogramming. class_eval紅寶石元編程(使用class_eval)

我有這樣的小項目,我們的目標是創建一個「 attr_accessor_with_history'方法,它將記錄分配給由其創建的變量的每個值。這裏是代碼:

class Class 
    def attr_accessor_with_history(attr_name) 
    attr_name = attr_name.to_s # make sure it's a string 
    attr_reader attr_name  # create the attribute's getter 
    attr_reader attr_name+"_history" # create bar_history getter 

    a = %Q{ 
     def initialize 
     @#{attr_name}_history = [nil] 
    end   

    def #{attr_name} 
     @#{attr_name} 
    end 

    def #{attr_name}=(new_value) 
     @#{attr_name}=new_value 
     @#{attr_name}_history.push(new_value) 
    end } 
     puts a 

     class_eval(a) 

    end 
end 

現在,當我測試一個變量的腳本。它工作正常。但是,當我嘗試創建兩個或多個變量(像這樣)......

class Foo 
attr_accessor_with_history :bar 
attr_accessor_with_history :lab 
end 

a = Foo.new 
a.bar = 45 
a.bar = 5 
a.bar = 'taat' 
puts a.bar_history 

b = Foo.new 
b.lab = 4 
b.lab = 145 
b.lab = 'tatu' 
puts b.lab_history 

....紅寶石給出了一個「不存在的‘推’的方法(class_eval)bar_history.push(NEW_VALUE )」。我認爲'initialize'方法在第二次調用attr_accessor_with_history時被覆蓋,所以第一個變量的記錄被破壞。

我不知道如何解決這個問題。我已經嘗試過撥打'超級'了。任何線索?

+3

哦,來吧,[在發佈之前做一點研究](http://stackoverflow.com/search?q=attr_accessor_with_history)。 –

+1

只要你知道這是一個來自edx.org軟件作爲服務課程的家庭作業項目。 – Dpolehonski

+0

謝謝你們。這是作業的一部分,是 – user1608920

回答

2

在你的setter方法只是檢查的歷史實例變量已經被初始化:

def #{attr_name}=(new_value) 
    @#{attr_name}=new_value 
    @#{attr_name}_history ||= [nil] 
    @#{attr_name}_history.push(new_value) 
end 

你需要爲你的歷史變量另一次吸氣,設置您的默認值,如果它沒有被前設置:

def #{attr_name}_history 
    @#{attr_name}_history ||= [nil] 
end 

然後,你可以刪除你的初始化方法,這是btw容易被覆蓋。

+0

''[nil]'應該是'[]'。 –

+0

@AlexD我不這麼認爲,因爲問題中歷史伊娃的初始狀態是'[無]'。如果這是一個好的方法,則取決於業務領域。 – unnu

+0

輝煌,謝謝unnu! – user1608920