通过关系删除 has_many Ruby on Rails

问题描述 投票:0回答:1

我有一个 Ruby on Rails 应用程序

我通过 user_unit_assocs 有一个具有多个用户的块。 该模型是这样定义的。

class Block < ActiveRecord::Base
  has_many :units, dependent: :destroy

class Unit < ActiveRecord::Base
  belongs_to :block
  has_many :users, :through => :user_unit_assocs, dependent: :destroy
  has_many :user_unit_assocs, dependent: :destroy

class User < ActiveRecord::Base
  has_many :units, :through => :user_unit_assocs
  has_many :user_unit_assocs, dependent: :destroy

问题是当我删除 Block 时 - 单位被删除 - user_unit_assoc 被删除 - 但该单位的用户不会被删除

我该如何解决这个问题以确保它也能级联阻止用户。问题是通过但我现在无法更改表结构,如何正确解决这些依赖记录删除问题。谢谢。

ruby-on-rails has-many-through has-many destroy
1个回答
0
投票

有一个新的 Ruby Gem 称为 Cascade Deleter ,可以在 Rails 中级联删除项目。这个 gem 相对于内置解决方案有很多优点 (

dependent: :destroy
)。

  1. 𝐒𝐢𝐦𝐩𝐥𝐢𝐜𝐢𝐭𝐲

“依赖”解决方案不仅需要您在要执行级联删除的所有模型上添加

dependent: :delete
/
dependent: :delete_all
,而且在删除根项时仍然会引发
Mysql2::Error: Cannot delete or update a parent row
MySQL 错误,以防万一您没有使用
foreign_key: { on_delete: :cascade }
设置所有数据库外键。

因此,例如,如果您要删除具有 50 个降序应用程序模型的 10 个项目,则需要在 50 个应用程序模型上添加

dependent: :delete
/
dependent: :delete_all
以及执行新的迁移,更改所有外键这些 50 张桌子
foreign_key: { on_delete: :cascade }
中的每一张。

相比之下,如果你决定使用

CascadeDeleter
,你只需要执行这个单行命令即可达到相同的目标:

CascadeDeleter.where(Project.where(id: (1..10))).delete_all
  1. 𝐅𝐥𝐞𝐱𝐢𝐛𝐢𝐥𝐢𝐭𝐲

另一个优点是,您可以对数据执行软删除而不是硬删除,这对于您想要停用项目而不是从数据库中完全删除项目的系统来说非常方便。

CascadeDeleter.where(Project.where(id: (1..10))).delete_all(method: :soft)
  1. 𝐏𝐞𝐫𝐟𝐨𝐫𝐦𝐚𝐧𝐜𝐞

最后,您还可以决定删除一组根项,而不是逐个删除这些根项。这可以在上面的示例中看到,它删除 10 个项目,而不是单独删除项目。这一事实提高了性能,因为对所需的表执行单个 SQL 删除操作。此过程也适用于降序类别。

© www.soinside.com 2019 - 2024. All rights reserved.