当我遇到一个令人沮丧的问题时,我正在做家庭作业。该作业是 Ruby 元编程中的一个练习,目标是定义一个“attr_accessor_with_history”,它与“attr_accessor”做所有相同的事情,但还提供一个属性曾经存在的所有值的历史记录。这是作业中提供的代码以及我为完成作业而添加的一些代码:
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s
attr_hist_name = attr_name+'_history'
history_hash = {attr_name => []}
#getter
self.class_eval("def #{attr_name} ; @#{attr_name} ; end")
#setter
self.class_eval %Q{
def #{attr_name}=(val)
# add to history
@#{attr_hist_name} = [nil] if @#{attr_hist_name}.nil?
@#{attr_hist_name} << val
history_hash[@#{attr_name}] = @#{attr_hist_name}
# set the value itself
@#{attr_name} = val
end
def history(attr) ; @history_hash[attr.to_s] ; end
}
end
end
class Foo
attr_accessor_with_history :bar
attr_accessor_with_history :crud
end
f = Foo.new # => #<Foo:0x127e678>
f.bar = 3 # => 3
f.bar = :wowzo # => :wowzo
f.bar = 'boo!' # => 'boo!'
puts f.history(:bar) # => [3, :wowzo, 'boo!']
f.crud = 42
f.crud = "Hello World!"
puts f.history(:crud)
我想使用散列来存储不同属性的不同历史记录,但我无法在 setter 的 class_eval 语句中访问该散列。无论我如何尝试设置它,我似乎总是为 []= 方法获得 NoMethodError,因为“history_hash”以某种方式变成 NilClass 类型,或者发生 NameError,因为它将“history_hash”视为未定义的局部变量或方法。如何在 class_eval 语句中使用哈希?