我有以下课程
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处理这种关系的方式,破坏产品,使市场不再与类别相关,所以它有删除它们的错觉!因此,不会调用类别上的任何销毁回调,因为类别不会被删除!
答案 0 :(得分:2)
您必须了解delete_all
和destroy_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_all
和before_destroy
回调集category_id = nil
更好地处理产品。
答案 2 :(得分:0)
market.categories.delete_all # delete instead of destroy
答案 3 :(得分:0)
好吧我想我知道答案:类别和市场是多对多的关系,所以当你说market.categories.delete_all
(或destroy_all)时,它试图打破这个市场与其类别之间的关系,这意味着删除连接记录,这是我们案例中的produtcs记录。