我正在尝试决定如何最好地为我的rails应用程序设置(如果有的话(外键约束。 我有一个模型Response
,belongs_to
Prompt
. 我想使用 :dependent => :destroy
对属于已删除Prompt
的每个Response
调用销毁,并且我正在尝试决定应该对我的外键放置什么删除约束。
简而言之,我想要有关如何充分利用依赖对象的销毁方法和外键约束的建议,以确保 cruft 不会累积并反映所存储数据的逻辑结构。 前面的几个问题,例如我应该在删除级联上使用吗,:d ependent => :d estroy,还是两者兼而有之?和 Rails:删除级联与依赖销毁 问哪个更好,但他们并没有真正说明这两个选择如何相互作用以及它们以什么顺序触发或在这一点上看起来很模糊。
在我看来,考虑因素似乎分为几部分:
:dependent => :destroy
从数据库中删除父对象之前,是否先对依赖对象调用 destroy,以便即使我使用级联删除,仍会对这些对象调用 destroy?
在从数据库中删除父对象之前(或在与从数据库中删除父对象的事务中(,
:dependent => :destroy
是否从数据库中删除依赖对象? 换句话说,如果我将级联设置为 nullify,数据库最终是否会在删除子对象之前浪费地取消子对象上的引用?删除是由于原始销毁和链接
:dependent => :destroy
选项包装在事务中而发出的,还是如果我不设置级联删除,会不幸地定时崩溃在数据库中留下垃圾?- 最后,如果我使用限制作为外键on_delete选项,
:dependent => :destroy
确保从数据库中删除父对象吗?
在事务中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将很乐意删除所有内容。