简体   繁体   English

如何在 habtm 关联的 Rails 中进行批量更新

[英]How to do bulk update in rails on habtm association

I have two models:我有两个模型:

#user.rb

has_and_belongs_to_many :groups

#group.rb

has_and_belongs_to_many :users

I want to associate groups to users such that many users can be associated to many groups .我想将组与用户相关联,以便many users can be associated to many groups

Front end side of the application is sending the user_ids and group_ids to the update method.应用程序的前端正在将user_idsgroup_ids发送到更新方法。

So in the UsersController , i've found out each user and associated that user with the groups.所以在UsersController ,我找到了每个用户并将该用户与组相关联。

def update
  users = User.where(id: [325, 326])
  users.each { |user| user.update(group_ids: [1, 2])}
end

I need to know the standard way of updating the associated records and what is the most efficient way of updating associated records?我需要知道更新关联记录的标准方法以及更新关联记录的最有效方法是什么?

There is a method update_all有一个方法update_all

def update
  users = User.where(id: [325, 326])
  users.update_all group_ids: [1, 2]
end

The simplest ActiveRecord-native approach is to create a model class for your join table and use that, eg:最简单的 ActiveRecord-native 方法是为您的连接表创建一个模型类并使用它,例如:

class GroupsUser < ActiveRecord::Base; end

(Note that the model class is GroupsUser so that by convention ActiveRecord will know it's for the groups_users table. It's a little goofy but it works.) (请注意,模型类是GroupsUser因此按照约定,ActiveRecord 会知道它是用于groups_users表的。这有点愚蠢,但它有效。)

Then you can use insert_all on the join table:然后你可以在连接表上使用insert_all

user_ids = [325, 326]
group_ids = [1, 2]

values = user_ids.map do |uid| 
           group_ids.map do |gid|
             { user_id: uid, group_id: gid }
           end
         end.flatten
# => [{user_id: 325, group_id: 1}, {user_id: 325, group_id: 2}, {user_id=>326, group_id: 1}, {user_id: 326, group_id: 2}]

GroupsUser.insert_all(values)

Note though that this is is insert_all , not update_all -- update_all doesn't really make sense for a join table.请注意,这是insert_all ,而不是update_all - update_all对于连接表没有真正意义。 We're adding values, not replacing them.我们正在添加值,而不是替换它们。 (At least on PostgreSQL and SQLite, if there's a unique index on the join table, duplicates will be ignored -- on MySQL you might need to jump through some more hoops to exclude existing relationships, unless you're deleting those anyway as below.) (至少在 PostgreSQL 和 SQLite 上,如果连接表上有唯一索引,则重复项将被忽略——在 MySQL 上,您可能需要跳过更多圈子以排除现有关系,除非您按如下方式删除它们。 )

If you want to replace any existing associations, you'll need to delete those explicitly:如果要替换任何现有关联,则需要明确删除这些关联:

ActiveRecord::Base.transaction do
  GroupsUser.delete_all(user_id: user_ids)
  # and/or GroupsUser.delete_all(group_id: group_ids), depending
  GroupsUser.insert_all(values)
end

Also worth noting: there's no need to put GroupsUser in app/models/groups_user.rb ;另外值得注意的是:没有必要将GroupsUser放在app/models/groups_user.rb if this is the only code that uses it, you can put it right in the file where it's used.如果这是唯一使用它的代码,您可以将它放在使用它的文件中。 This is especially useful in migrations.这在迁移中特别有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM