【发布时间】:2015-04-01 14:06:57
【问题描述】:
在 RSpec 测试中,我创建了一个包含多个记忆值的记录。
foo.reload 对对象的属性按预期工作,但记忆中的属性仍然存在。
到目前为止,它通过完全重新创建对象来工作:foo = Foo.find(123),但在我的例子中,查找记录的逻辑实际上更复杂。
什么是完全重新加载记录并清除所有记忆值的好方法?
【问题讨论】:
标签: ruby-on-rails ruby activerecord rspec
在 RSpec 测试中,我创建了一个包含多个记忆值的记录。
foo.reload 对对象的属性按预期工作,但记忆中的属性仍然存在。
到目前为止,它通过完全重新创建对象来工作:foo = Foo.find(123),但在我的例子中,查找记录的逻辑实际上更复杂。
什么是完全重新加载记录并清除所有记忆值的好方法?
【问题讨论】:
标签: ruby-on-rails ruby activerecord rspec
好方法是您已经拥有的方法:完全重新创建对象。
您不能以任何简单的“Rails”方式“重新加载”对象的记忆值,因为记忆属性不是 Rails 或 ActiveRecord 的功能。两者都不知道你是如何记忆方法的。
【讨论】:
您可以通过重新定义reload 来做到这一点。例如,如果您使用 ||= 进行记忆,您可以这样做:
class Foo < ActiveRecord::Base
def bar
@bar ||= rand
end
def reload
@bar = nil
super
end
end
有关重置所有实例变量的方法,请参阅Is there a clean API for resetting instance variables on 'reload' in ActiveRecord?
如果您使用memoist gem,您可以在那里调用flush_cache。
【讨论】:
Michael 的回答是正确的,但请注意,如果您使用 the more sophisticated pattern for also memoization nil and false values,则不会重置记忆。
例如,使用文章中的相同示例来记忆 nil 和 false 值:
def main_address
return @main_address if defined? @main_address
@main_address = begin
main_address = get_home_address_from_api
main_address ||= get_work_address_from_api
main_address ||= another_api_call.first
end
end
这种模式很有效,因为它还记忆了nil 和false,但是当然,要重置它,只需将@main_address 设置为nil 是不够的,因为它已经是被定义并尽早返回。
在这些情况下,您应该像这样重置它:
def reset_main_address_memoization
self.send(:remove_instance_variable, :@main_address) if instance_variable_defined?(:@main_address)
end
【讨论】: