我正在尝试决定如何最好地为我的rails应用程序设置(如果有的话)外键约束。我有Response
belongs_to
的模型Prompt
。我想使用:dependent => :destroy
对属于已删除Response
的每个Prompt
进行销毁调用,并且我正在尝试确定应该对外键执行哪些删除约束。< / p>
简而言之,我想知道如何最好地利用依赖对象的destroy方法和外键约束来确保cruft不会累积并反映存储数据的逻辑结构。之前的几个问题,如Should I use ON DELETE CASCADE, :dependent => :destroy, or both?和Rails: delete cascade vs dependent destroy,问哪个更好,但他们并没有真正说明这两个选择如何相互作用,以及它们被触发的顺序或看起来模糊不清。
正如我所看到的那样,考虑因素似乎分为几个部分:
:dependent => :destroy
是否首先调用依赖对象的销毁,因此即使我使用级联删除,仍会在这些对象上调用destroy? :dependent => :destroy
是否从数据库中删除父项之前(或在事务中)从数据库中删除依赖对象?换句话说,如果我将cascade设置为nullify,那么数据库最终会在删除子对象之前浪费地取消它们的引用吗?
是否由于原始销毁和链接:dependent => :destroy
选项包含在事务中而发出删除,或者遗憾的是,如果我没有设置级联删除,那么定时崩溃会在数据库中丢失?
:dependent => :destroy
确保从数据库中删除父对象吗?答案 0 :(得分:2)
在事务中使用dependent: :destroy
时,rails首先会破坏所有依赖关系,然后才删除记录本身。
可能存在争用条件:如果在rails读取要销毁的集合后添加了相关记录,但尚未删除父记录,则该记录会被保留。我们将这些称为“比赛条件记录”。
是的,您可以使用dependent: :destroy
和on delete cascade
,这样可以删除某些子项(竞赛条件项)而无需回调。如果回调是强制性的-on delete restrict
加上一些锁定和显式子级删除可能会更好。
这有点像validates :some_field, uniqueness: true
,最好由唯一索引支持,只有数据库本身才能确保数据一致性。
由于上次删除了父项,因此on delete nullify
不会妨碍您的访问(您将获得无效的比赛条件记录)
其中包含所有删除内容的交易记录,只能保留比赛条件记录
on delete restrict
上的 dependent: :destroy
仅会触发竞争条件记录(并回滚整个事务),但是如果没有竞争条件-Rails会很乐意删除所有内容。