Rails用两者做什么:dependent => :destroy和cascade delete / nullify / restrict

时间:2016-02-15 15:51:30

标签: ruby-on-rails foreign-keys cascade dependent-destroy

我正在尝试决定如何最好地为我的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,问哪个更好,但他们并没有真正说明这两个选择如何相互作用,以及它们被触发的顺序或看起来模糊不清。

正如我所看到的那样,考虑因素似乎分为几个部分:

  1. 在从数据库中删除父项之前,:dependent => :destroy是否首先调用依赖对象的销毁,因此即使我使用级联删除,仍会在这些对象上调用destroy?
  2. :dependent => :destroy是否从数据库中删除父项之前(或在事务中)从数据库中删除依赖对象?换句话说,如果我将cascade设置为nullify,那么数据库最终会在删除子对象之前浪费地取消它们的引用吗?

  3. 是否由于原始销毁和链接:dependent => :destroy选项包含在事务中而发出删除,或者遗憾的是,如果我没有设置级联删除,那么定时崩溃会在数据库中丢失?

  4. 如果我使用restrict作为外键on_delete选项,最后将:dependent => :destroy确保从数据库中删除父对象吗?

1 个答案:

答案 0 :(得分:2)

在事务中使用dependent: :destroy时,rails首先会破坏所有依赖关系,然后才删除记录本身。

可能存在争用条件:如果在rails读取要销毁的集合后添加了相关记录,但尚未删除父记录,则该记录会被保留。我们将这些称为“比赛条件记录”。

  1. 是的,您可以使用dependent: :destroyon delete cascade,这样可以删除某些子项(竞赛条件项)而无需回调。如果回调是强制性的-on delete restrict加上一些锁定和显式子级删除可能会更好。 这有点像validates :some_field, uniqueness: true,最好由唯一索引支持,只有数据库本身才能确保数据一致性。

  2. 由于上次删除了父项,因此on delete nullify不会妨碍您的访问(您将获得无效的比赛条件记录)

  3. 其中包含所有删除内容的交易记录,只能保留比赛条件记录

  4. on delete restrict上的
  5. dependent: :destroy仅会触发竞争条件记录(并回滚整个事务),但是如果没有竞争条件-Rails会很乐意删除所有内容。