【问题标题】:Rails: delete on scoped association behaves differently than just delete from the associationRails:作用域关联上的删除行为与仅从关联中删除不同
【发布时间】:2018-05-31 11:56:24
【问题描述】:

我有一个基于 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-rails scope associations


    【解决方案1】:

    当您在options 关系中调用materials 方法时,它会返回一个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

    【讨论】:

    • OP 的 Item.first.options.materialsItem.first.options 实际上都返回 Option 记录(或“关系实例”,用你的话来说,据我理解你的陈述)。然而,它们是不同的实例类型:Item.first.options.materials 返回 Option::ActiveRecord::AssociationRelation 类型,而 Item.first.options 返回 Option::ActiveRecord::Associations::CollectionProxy 类型。我的直觉是,这种差异在某处导致了对 OP 问题的解释。但目前我无法验证。
    • @Jay-ArPolidario 您对不同的返回类型是正确的。尽管如此,我希望删除方法在这两种情况下都有效。我想在 Option 模型上定义范围,因为我可以在其他情况下重用它们。
    • 正确,两个返回选项。这里的关键部分是关系的类型,它们的行为不同
    • 好的@sickrandir,编辑了答案。现在重用materials 范围,这是一个更好的解决方案。
    • 谢谢!您能否解释一下或向我指出一些文档以了解为什么作用域返回 Relation 而不是 CollectionProxy?
    猜你喜欢
    • 1970-01-01
    • 2012-07-09
    • 2022-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多