如何避免 Rails 缓存导致子对象看起来不存在
Posted
技术标签:
【中文标题】如何避免 Rails 缓存导致子对象看起来不存在【英文标题】:How to avoid Rails caching from causing child objects to appear to not exist 【发布时间】:2021-04-11 07:46:16 【问题描述】:我正在处理一个订单应用程序,它接受来自 CC 处理供应商的订单,并将它们传递给一个履行应用程序。
class Order < ApplicationRecord
has_many :items, class_name: 'Product'
def payload
@builder = Nokogiri::XML::Builder.new do |xml|
...
self.items.each do |o|
...
end
end
@builder.to_xml
end
...
end
当订单进来时,它会创建所有需要的记录,然后尝试将有效负载传递给履行应用程序
def generate_order
ActiveRecord::Base.transaction do
# create order
...
External.send_order(self) # Web Call to Customer Support system <= this is were caching is happening
Product.create!(...) #create the actual product items
p "Payload #self.payload"
rescue StandardError => e
...
end
end
因为我们将订单本身传递给客户支持系统,所以在我们实际处理商品之前,Rails 会缓存不含任何商品的订单。因此,当我们尝试查看有效负载时,这些项目不存在。
我可以将标注移至客户支持系统,直到我们处理完项目并解决它,但是..
我们如何确保我们使用的是订单的当前/非缓存版本?
【问题讨论】:
我认为这与缓存无关。这条线p "Payload #self.payload"
实际上在事务块内吗?问题可能是事务尚未提交,这意味着您尝试检索的记录实际上并不存在。您可以发布有关调用此方法的日志吗?
@engineersmnky 感谢您的回复。它在事务块中,但是将 External.send_order(self) 移到 Product.create!() 之后允许“Payload #self.payload”查看已创建的项目。
我不知道External::send_order
做了什么,因为这段代码没有发布,但你可以reload
payload
中的关联,例如self.items.reload
@engineersmnky 谢谢! reload 方法是我正在寻找的。如果您可以将其作为答案,我会将其标记为已接受。
【参考方案1】:
从评论中复制:我不知道External::send_order
做了什么,因为这段代码没有发布。
也就是说,如果您有缓存的关系并且希望更新它,您可以使用ActiveRecord::Relation#reload
来执行此操作。例如
self.items.reload.each do |o|
#...
end
此方法所做的是重置关系,然后再次加载记录。这意味着它将触发查询以重新收集关系的所有记录,因此请注意在何处以及如何使用它(不建议在循环或迭代器中使用它)
【讨论】:
以上是关于如何避免 Rails 缓存导致子对象看起来不存在的主要内容,如果未能解决你的问题,请参考以下文章
如果对象在 Rails 6 中以嵌套形式不存在,如何创建对象?