Rails:删除级联vs依赖destroy

apo*_*try 27 postgresql referential-integrity ruby-on-rails

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

rails中的最佳实践(速度,样式和参照完整性)是什么,以确保删除用户时,所有相关订单也会被删除?我正在考虑以下选项:

案例1. :dependent => :destroy在用户模型中使用

案例2.在postgres中定义表顺序并写入

user_id integer REFERENCES users(id) ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*own 30

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

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


Wir*_*dIn 19

has_many :orders, dependent: :destroy

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


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

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


has_many :orders, dependent: :delete_all

  • 仅在has_many是关联树上的叶节点时使用(即,子节点没有与外键引用的另一个has_many关联)


小智 6

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

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

当然,我希望选项2更快,但如果权衡价值,这取决于你.删除用户是您应用程序中的常见操作吗?

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