[英]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_ids
和group_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.