我应该使用ON DELETE CASCADE,:dependent => :毁灭,或两者兼而有之?

时间:2009-07-27 18:57:43

标签: mysql ruby-on-rails ruby activerecord

在Rails应用程序中,我在MySQL中有外键约束,我将它们全部手动设置,与我的迁移分开。

我正在试图弄清楚是否应该使用ActiveRecord的:dependent => :destroy选项。例如,在我的架构中,我有表格......

users
-----

log_entries
-----------
user_id  # Has FK constraint to users.id with ON DELETE CASCADE

在我的模特中我可以......

class User < ActiveRecord::Base
  has_many :log_entries, :dependent => :destroy
end

我应该在模型上省略相关选项并将其留给数据库吗?或者那里有那个好吗?删除此应用程序中的内容时,我不需要运行任何回调。在所有情况下,只需删除它们即可。

要考虑的另一个因素是我的测试环境中不会出现FK约束,可能是因为rake db:test:prepare没有设置它们。因此,如果我完全依赖MySQL来级联删除,那么很难测试会发生什么。

3 个答案:

答案 0 :(得分:7)

你不应该使用dependent =&gt; :如果您的FK具有ON DELETE CASCADE,则在模型中销毁。它可以运行不必要的查询,你不能指望它不会在将来破坏它。您应该在模型文件中添加注释以记录它正在发生的事情。虽然。

我还建议在迁移中执行FK。如果您的测试数据库与生产数据库具有相同的约束,那会更好,这可能会导致非常狡猾的错误。有一个RedHill插件(redhillonrails_core)使迁移中的外键变得容易,并且启用了具有FK约束的模式转储,因此测试更加简单。

答案 1 :(得分:3)

我要添加:dependent =&gt; :在那里摧毁只是因为它传达了意图。更重要的是,并非所有数据库都支持DELETE CASCADE,因此数据库适配器将负责确定如何最好地删除关联的记录。在我看来,至少把它放在模型中是更重要的。但把它放在两者都是正确的答案。

答案 2 :(得分:3)

取决于。 :dependent =&gt; :destroy将加载每个子模型和运行回调。 ON DELETE CASCADE不会运行任何回调,但速度很快。

如果您只想摆脱模型,可以选择ON DELETE CASCADE,或者使用:dependent =&gt; :delete_all,它只运行1个查询,而不是N + 1。