如何防止Rails在某些关系上级联删除

时间:2015-12-17 08:48:51

标签: ruby-on-rails activerecord

我有以下课程

class Market < ActiveRecord::Base
 has_many :products
 has_many :categories, through: :products
end

class Product < ActiveRecord::Base
 belongs_to :market
 belongs_to : category
end

class Category < ActiveRecord::Base
 has_many :products
 has_many :markets, through: :products
end

现在使用以下代码:

market = .. #some market
market.categories.destroy_all

市场产品也被删除了!如何防止这种情况?

修改 类别不会被删除,但只有产品!并且使用market.categories.delete_all仅在一个查询中删除产品而不是多个,但不再删除类别!看来这是rails处理这种关系的方式,破坏产品,使市场不再与类别相关,所以它有删除它们的错觉!因此,不会调用类别上的任何销毁回调,因为类别不会被删除!

4 个答案:

答案 0 :(得分:2)

您必须了解delete_alldestroy_all之间的区别。

第一个将只执行SQL DELETE。

delete_all上的文档:

  

删除匹配条件的记录而不实例化   首先记录,因此不调用destroy方法也不调用   回调。这是一个直接的SQL DELETE语句   数据库,比destroy_all更有效。小心   但是关系特别是:依赖规则定义的   协会不予尊重。返回受影响的行数。

来自destroy_all上的文档:

  

注意:每个记录的实例化,回调执行和删除   一次删除多条记录时可能会非常耗时。它   每条记录至少生成一个SQL DELETE查询(或者更多,   强制执行你的回调)。如果要快速删除多行,   如果不关心它们的关联或回调,请使用delete_all   代替。

因此,为了不执行回调,您应该求助于删除,而不是销毁。相反,当你有回调时,销毁更可取。

答案 1 :(得分:0)

market = .. #some market
market.categories.delete_all

但删除类别会引发产品记录问题。使用destroy_allbefore_destroy回调集category_id = nil更好地处理产品。

答案 2 :(得分:0)

market.categories.delete_all # delete instead of destroy

答案 3 :(得分:0)

好吧我想我知道答案:类别和市场是多对多的关系,所以当你说market.categories.delete_all(或destroy_all)时,它试图打破这个市场与其类别之间的关系,这意味着删除连接记录,这是我们案例中的produtcs记录。

相关问题