ruby 如何完全重新加载ActiveRecord以重置其记忆值?

jw5wzhpr  于 2023-04-11  发布在  Ruby
关注(0)|答案(3)|浏览(107)

在一个RSpec测试中,我创建了一个记录,其中有几个memoized值。
foo.reload按照对象属性的预期工作,但记忆化的属性仍然存在。
到目前为止,它的工作原理是完全重新创建对象:foo = Foo.find(123)但在我的例子中,查找记录的逻辑实际上更复杂。
什么是一个好的,干燥的方式完全重新加载记录和删除所有的记忆值?

vsmadaxz

vsmadaxz1#

你可以通过重新定义reload来实现。例如,如果你使用||=进行memoized,你可以这样做:

class Foo < ActiveRecord::Base
  def bar
    @bar ||= rand
  end

  def reload(options = nil)
    @bar = nil
    super
  end
end

有关重置所有示例变量的方法,请参见Is there a clean API for resetting instance variables on 'reload' in ActiveRecord?
如果你使用memoist gem,你可以在这里调用flush_cache

bvpmtnay

bvpmtnay2#

Michael的回答是合理的,但要注意,如果您使用the more sophisticated pattern for also memoization nil and false values,这将不会重置备忘录。
例如,使用文章中的相同示例存储nilfalse值:

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

这个模式很好用,因为它还存储了nilfalse,但是当然,要重置它,简单地将@main_address设置为nil是不够的,因为它已经被定义并提前返回。
在这些情况下,您应该像这样重置它:

def reset_main_address_memoization
  self.send(:remove_instance_variable, :@main_address) if instance_variable_defined?(:@main_address)
end
ffscu2ro

ffscu2ro3#

好的方法是你已经拥有的:完全重新创建对象。
你不能用任何简单的“Rails”方式“重新加载”对象的记忆值,因为记忆属性不是Rails或ActiveRecord的功能,它们都不知道你如何记忆方法。

相关问题