有条件地为活动记录中的多对多关系创建新记录
Conditionally create new records for many to many relationship in activerecords
我正在与 ActiveRecord
一起从事 RoR
项目,我对这些技术还很陌生。
我有两个模型:
User.rb
class User < ApplicationRecord
...
has_and_belongs_to_many :roles
...
Role.rb
class Role < ApplicationRecord
...
has_and_belongs_to_many :users
...
所以现在我正在创建一个新角色:
Role.where(name: 'my_new_role').first_or_create!
并且我想创建一个 rake 任务,它将为已经拥有 admin
角色的用户和所有其他没有 unfit_role
角色的用户添加这个角色。
如果我使用纯 SQL
执行此操作,我很可能会执行 select 来收集我要更新的所有用户 ID,然后对我的所有 ID 执行另一个更新查询'已收集。
但是我觉得 ActiveRecord
有一些细节我还不太理解,但我决定尝试其他方法。
目前我有这个代码:
new_role = Role.where(name: :my_new_role).first
User.all.each do |entity|
entity.roles << new_role if entity.has_role?('admin')
entity.roles << new_role if !entity.has_role?('unfit_role')
end
而 has_role
是简单的辅助方法,它 select 所有角色一次,并使用 include?
检查给定角色是否在 selected 角色列表中.
基于 1-2 次试运行,似乎这确实有效,但我真的不喜欢这个实现。主要是我检查某个用户(实体)是否具有给定角色的方式。我觉得这是执行相对简单任务的一种非常低效的方法,所以我想知道如何以不同的方式实现它以便更快。
您可以使用 Postgres aggregate functions 来提高查询效率:
new_role = Role.where(name: 'my_new_role').first!
admin_role = Role.where(name: 'admin').first!
unfit_role = Role.where(name: 'unfit_role').first!
User.joins(:roles).group(:id).having("bool_or(roles.id = #{admin_role.id}) or not bool_or(roles.id = #{unfit_role.id})").each do |entity|
entity.roles << new_role
end
我正在与 ActiveRecord
一起从事 RoR
项目,我对这些技术还很陌生。
我有两个模型:
User.rb
class User < ApplicationRecord
...
has_and_belongs_to_many :roles
...
Role.rb
class Role < ApplicationRecord
...
has_and_belongs_to_many :users
...
所以现在我正在创建一个新角色:
Role.where(name: 'my_new_role').first_or_create!
并且我想创建一个 rake 任务,它将为已经拥有 admin
角色的用户和所有其他没有 unfit_role
角色的用户添加这个角色。
如果我使用纯 SQL
执行此操作,我很可能会执行 select 来收集我要更新的所有用户 ID,然后对我的所有 ID 执行另一个更新查询'已收集。
但是我觉得 ActiveRecord
有一些细节我还不太理解,但我决定尝试其他方法。
目前我有这个代码:
new_role = Role.where(name: :my_new_role).first
User.all.each do |entity|
entity.roles << new_role if entity.has_role?('admin')
entity.roles << new_role if !entity.has_role?('unfit_role')
end
而 has_role
是简单的辅助方法,它 select 所有角色一次,并使用 include?
检查给定角色是否在 selected 角色列表中.
基于 1-2 次试运行,似乎这确实有效,但我真的不喜欢这个实现。主要是我检查某个用户(实体)是否具有给定角色的方式。我觉得这是执行相对简单任务的一种非常低效的方法,所以我想知道如何以不同的方式实现它以便更快。
您可以使用 Postgres aggregate functions 来提高查询效率:
new_role = Role.where(name: 'my_new_role').first!
admin_role = Role.where(name: 'admin').first!
unfit_role = Role.where(name: 'unfit_role').first!
User.joins(:roles).group(:id).having("bool_or(roles.id = #{admin_role.id}) or not bool_or(roles.id = #{unfit_role.id})").each do |entity|
entity.roles << new_role
end