Rails:删除级联vs依赖destroy
假设我有两个表: users
和orders
。 用户有很多订单,因此我的订单表中自然会有一个外键user_id。
rails中的最佳实践(在速度,样式和参照完整性方面)是什么,以确保如果删除用户,所有相关订单也会被删除? 我正在考虑以下选项:
案例1.在用户模型中使用:dependent => :destroy
案例2.在postgres中定义表顺序并写入
user_id integer REFERENCES users(id) ON DELETE CASCADE
我有什么理由要使用案例1吗? 似乎案例2正在做我想做的一切吗? 执行速度有区别吗?
这实际上取决于你想要的行为。 在案例1中,将在每个关联的订单上调用destroy,因此ActiveRecord回调也是如此 。 在案例2中,这些回调不会被触发,但会更快并保证参照完整性。
在应用程序的初期,我建议使用:dependent => :destroy
因为它让你以独立于数据库的方式开发。 一旦开始扩展,您应该出于性能/完整性原因在数据库中开始这样做。
has_many :orders, dependent: :destroy
- 最安全的选项,可自动维护数据完整性。
- 您有多态关联,并且不想使用触发器。
add_foreign_key :orders, :users, on_delete: :cascade
(在数据库迁移中)
- 您没有使用任何多态关联,或者您希望为每个多态关联使用触发器。
has_many :orders, dependent: :delete_all
- 仅在has_many是关联树上的叶节点时使用(即,子节点没有与外键引用的另一个has_many关联)
我会使用选项1.虽然它可以工作,但我可以看到选项2的一些问题:
- ActiveRecord将不会意识到这些记录已被删除,这可能导致行为不稳定
- 任何阅读代码的人都不清楚删除用户意味着他们的所有订单也将被删除
- 订单上的任何
destroy
处理程序都不会触发
当然,我希望选项2更快,但如果权衡价值,这取决于你。 删除用户是否是应用程序中的常见操作?
另一种选择是使用:dependent => :delete_all
。 这比:dependent => :destroy
更快:dependent => :destroy
并避免上面的缺点1和2。 有关详细信息,请参见此处