我有这个小项目,目标是创建一个'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
.... Ruby为(class_eval)bar_history.push(new_value)提供了一个“不存在的'push'方法”。我认为'initialize'方法在第二次调用attr_accessor_with_history时被覆盖,因此第一个变量的记录被破坏。
我不知道如何解决这个问题。我已经尝试过调用'超级'。任何线索?
答案 0 :(得分:2)
在你的setter方法中,只需检查历史实例变量是否已经初始化:
def #{attr_name}=(new_value)
@#{attr_name}=new_value
@#{attr_name}_history ||= [nil]
@#{attr_name}_history.push(new_value)
end
如果之前没有设置默认值,您需要为历史变量设置另一个getter:
def #{attr_name}_history
@#{attr_name}_history ||= [nil]
end
然后你可以删除你的初始化方法,这很容易被覆盖。