型号:
Class Checklist
has_many :checklist_items
end
Class ChecklistItem
belongs_to :checklist
after_save :update_checklist_completion
def update_checklist_completion
if siblings.unchecked.any?
checklist.update(completed: false)
else
checklist.update(completed: true)
end
end
end
保存清单项目后,它会运行
update_checklist_completion
- 如果清单上的所有其他清单项目也已完成,那么它将更新要完成的清单。问题是,如果清单项目完成得太快,那么当该方法在最后一个清单项目上运行时,之前的清单项目尚未完成更新,因此无法将清单项目标记为已完成。
我相信这是一个竞争条件。我的想法是,最好在执行
update_checklist_completion
时防止兄弟姐妹被更新,但不确定实现此目的的最佳方法。我看过 Mutex
但这似乎阻止了在该对象上访问该方法。就我而言,我认为我需要阻止其他对象(兄弟姐妹)更新
可能回调,尤其是非数据库回调不太适合此目的
如果需要,您可以锁定所有记录(父项和所有子项)。然后在打开的事务中保存子记录,检查其他子记录并更新父记录
类似这样的:
checklist.with_lock do
checklist.checklist_items.lock!
checklist_item.save!
completed = !checklist.checklist_items.unchecked.exists?
checklist.update!(completed:)
end
注意:如果在不同的地方应用不同的锁定顺序,就会出现死锁