39

假设我有两个表:usersorders. 一个用户有很多订单,所以我的订单表中自然有一个外键 user_id。

Rails 中的最佳实践是什么(在速度、样式和引用完整性方面),以确保如果删除用户,所有相关订单也被删除?我正在考虑以下选项:

案例一:dependent => :destroy、在用户模型中使用

案例 2. 在 postgres 中定义表 order 并编写

user_id integer REFERENCES users(id) ON DELETE CASCADE

我有什么理由应该使用案例 1?似乎案例 2 正在做我想做的一切?执行速度有区别吗?

4

3 回答 3

37

这实际上取决于您想要的行为。在情况 1 中,将在每个关联订单上调用 destroy,因此ActiveRecord 回调也将调用。在情况 2 中,不会触发这些回调,但它会更快并保证引用完整性。

在应用程序的初期,我建议您使用它,:dependent => :destroy因为它可以让您以独立于数据库的方式进行开发。一旦开始扩展,出于性能/完整性的原因,您应该开始在数据库中进行扩展。

于 2012-09-23T22:32:29.840 回答
25

has_many :orders, dependent: :destroy

  • 自动维护数据完整性的最安全选项。
  • 您有多态关联,并且不想使用触发器。


add_foreign_key :orders, :users, on_delete: :cascade(在数据库迁移中)

  • 您没有使用任何多态关联,或者您想为每个多态关联使用触发器。


has_many :orders, dependent: :delete_all

  • 仅当 has_many 是关联树上的叶节点时使用(即子节点没有与外键引用的另一个 has_many 关联)
于 2015-06-28T20:11:15.563 回答
8

我会使用选项 1。虽然它可能有效,但我可以看到选项 2 的一些问题:

  1. ActiveRecord 将不知道这些记录已被删除,这可能导致不稳定的行为
  2. 阅读代码的任何人都不清楚删除用户意味着他们的所有订单也将被删除
  3. Order 上的任何destroy处理程序都不会触发

当然,我希望选项 2 更快,但是否值得权衡取舍取决于您。删除用户是您的应用程序中的常见操作吗?

另一种选择是使用:dependent => :delete_all. :dependent => :destroy这将比上面的缺点 1 和 2更快并避免。有关更多详细信息,请参见此处

于 2012-09-23T22:31:13.043 回答