【问题标题】:Rails: How to update all through ActiveRecord_RelationRails:如何通过 ActiveRecord_Relation 全部更新
【发布时间】:2018-11-08 17:53:02
【问题描述】:

我通过 has_one 有两个相关模型,如下所示:

class Asset
  has_one :device

class Device
  belongs_to :asset

我有这样的资产的 ActiveRecord_Relation:

assets = Asset.all

我需要为每个资产更新每个设备中的一个字段。我不想为每个相关设备创建一个数组,因为它效率很低。我试过这样的事情:

assets.joins(:device).update_all( {:device=>{:my_field=>6} )

【问题讨论】:

  • 有什么原因不能直接用Device.update_all 更新Device?是否存在不属于资产的设备?
  • Asset.all 是一个简化的示例。实际上,ActiveRecord_Relation 是通过基于各种搜索条件的大量范围计算得出的。搜索完成后,我在 ActiveRecord_Relation 中剩下 100k 资产模型。

标签: ruby-on-rails ruby-on-rails-5 rails-activerecord


【解决方案1】:

你可以使用 SQL:

assets.joins(:device).update_all(["devices.my_field=?", 6])

或者如果该字段依赖于其他字段:

assets.joins(:device).update_all("devices.my_field=assets.other_field")

【讨论】:

  • 您的第一个建议导致:ActiveRecord::StatementInvalid: PG::UndefinedColumn: 错误:关系“资产”的“设备”列不存在。它使用了这个 SQL: UPDATE "assets" SET devices.os_id=6 WHERE "assets"."id" IN (SELECT "assets"."id" FROM "assets" INNER JOIN "devices" ON "devices"."asset_id" = "资产"."id")
【解决方案2】:

解决办法是这样的:

assets = Asset.some_scope.some_other_scope
devices = Device.where("devices.asset_id IN (?)", assets.select(:id))
devices.update_all("devices.my_field=?", 6)

这使用单个数据库查询通过它们与资产的关系来更新所有关联设备。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2013-08-23
    相关资源
    最近更新 更多