首页 > 解决方案 > Rails:作用域关联上的删除行为与仅从关联中删除不同

问题描述

我有一个基于 Rails 4.2 的项目。

我已经定义了两个这样的模型:

class Option < ActiveRecord::Base
    has_many :item_options
    has_many :items, through: :item_options, source: :item 

    scope :materials, -> { where(category: 'material') }
    scope :types, -> { where(category: 'type') }

class Item < ActiveRecord::Base
    has_many :item_options
    has_many :options, through: :item_options

我无法通过 Option 模型的范围删除关联的加入记录。

如果我做:

Item.first.options.materials.delete_all

执行的查询是:

DELETE FROM "options" WHERE "options"."id" IN (SELECT "options"."id" FROM "options" INNER JOIN "item_options" ON "options"."id" = "item_options"."option_id" WHERE "item_options"."item_id" = $1 AND "options"."category" = $2)

这从 Option 模型中删除了记录,这不是我所期望的。

如果我尝试在不使用范围的情况下删除关联记录,如下所示:

Item.first.options.delete_all

正确执行查询:

DELETE FROM "item_options" WHERE "item_options"."item_id" = $1

有效地仅删除连接记录。

如果通过范围调用,为什么 delete 的行为会有所不同?

(已编辑,其中一个模型包含旧名称 LabelItem 的粘贴错误)

标签: ruby-on-railsscopeassociations

解决方案


当您materialsoptions关系中调用该方法时,它会返回一个Option关系实例。这就是为什么它不起作用。

它可能有效:

class Item < ActiveRecord::Base
    has_many :item_options
    has_many :options, through: :item_options
    has_many :material_options, -> { materials }, through: :item_options, source: :option

然后:

Item.first.material_options.delete_all


推荐阅读