【问题标题】:update_all method not working for associated recordsupdate_all 方法不适用于关联记录
【发布时间】:2017-04-27 07:43:16
【问题描述】:

我有两个模型,它们之间的关联是has_and_belongs_to_many。 我需要重构代码,因为它会导致 n + 1 个查询。

问题:n+1 个查询

1.任务

    class Task < ActiveRecord::Base
      has_and_belongs_to_many :user_groups
    end

2。用户组

    class UserGroup < ActiveRecord::Base
      has_and_belongs_to_many :tasks
    end

要求:

将任务分配给 user_groups

以前的控制器代码:

task_ids.each do |task_id|
 find(task_id).update_attributes! user_group_ids: params[:user_group_ids], release_date: params[:release_date]
end

我的尝试:

tasks = Task.where(id: task_ids)
tasks.update_all(user_group_ids: params[:user_group_ids], release_date: params[:release_date])

错误:

ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column 关系“tasks”的“user_group_ids”不存在

查询生成:

SQL (0.6ms) UPDATE "tasks" SET "user_group_ids" = 4, "release_date" = '2017-04-27 07:40:26.525357' 其中 "tasks"."deleted_at" 为 NULL 并且 "tasks"."id" = 47394

请告诉我如何使用update_all

【问题讨论】:

    标签: ruby-on-rails postgresql ruby-on-rails-4 update-all


    【解决方案1】:

    为什么必须创建 UserGroup 模型?这不是我们使用habtm 关系的方式。

    你的模特Task,在这一切的中间,让我有点困惑。你需要做什么?我怀疑你在Task 中没有habtm 关系。

    对于您遇到的错误,这是完全可以理解的。 tasks 表中没有名为 user_group_ids 的属性(列)。而且,对于habtm 关系,user_group_ids 这个属性对我来说似乎拼写错误。

    无论如何,对于habtm 关系,如果您的用户有很多组并且一个组可以有很多用户,那么您走在正确的道路上,但是对于 Ruby on Rails,您可以通过两种方式来实现。

    1. 如果您不需要管理关系表中的其他数据(关系属性):

      • 那么在您的情况下,您只需要表格groups_users。 Rails 将按字母顺序查找habtm 关系表。
    2. 如果您的groups_users 关系包含模型的参考ID 以外的任何其他数据,那么您最好使用has_many :through 关系。

      • 在这种情况下,您的 UserGroup(请注意奇点)表将保存您在关系中需要的其他数据。然后你声明如下:

      • User 模型将声明:has_many :groups, through: :user_groups

      • Group 模型将声明:has_many :users, through: :user_groups
      • UserGroup 型号:belongs_to :userbelongs_to :group。请注意不要将其中任何一个索引为唯一、数据库或应用程序级别。

    更多详情请查看http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

    希望你得到你的结果!

    【讨论】:

    • user_group 表具有业务逻辑,因此已添加。如用户可以属于多个组,并且组可以根据其权限同时具有访问权限。
    • 我可以添加has_many through association。逻辑是我需要assign tasks to different user_groups,但它之前的编写方式导致n+1 查询。我需要解决这个问题。
    • 我可以看到,但问题是您的任务表中没有 user_group_ids 列。您可以通过编写迁移来添加该列来解决这个问题,但我的感觉是您有一个尚不可见的建模问题 - 您的关系似乎令人困惑。
    • 如果使用问题中提到的update_attributes,连接表将自动添加它。 update_all 的查询格式错误。
    • @Ahmadhamza 你明白了吗?我正在尝试做同样的事情。我希望 Rails 能够检测到我正在尝试更新关联关系,就像我执行 task.user_ids = (ids) 一样,但它似乎不起作用。我正在寻找解决方法,因为我不想弄脏拆分参数并通过循环。
    【解决方案2】:

    您的解决方案(不会导致 N+1)是 activerecord-import

    【讨论】:

      【解决方案3】:

      您不能使用 update_all 批量分配关联。 update_all 执行单个 UPDATE 查询,但对于关联,您实际上需要一个 INSERT 查询来插入关联的模型。您可以使用像 bulk_insert 这样的 gem 通过一个 INSERT 查询 https://github.com/jamis/bulk_insert 插入所有连接对象

      【讨论】:

        猜你喜欢
        • 2015-09-03
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 2022-10-21
        • 1970-01-01
        • 2019-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多