如何在同一关联中选择具有两个约束的记录?

时间:2012-09-11 00:14:55

标签: ruby-on-rails ruby-on-rails-3 roles

我希望能够选择具有多个角色的用户:

User < ActiveRecord::Base
  has_and_belongs_to_many :roles
end

Role < ActiveRecord::Base
  has_and_belongs_to_many :users
end

我知道如何选择具有以下两种角色之一的用户:

User.joins(:roles).where(roles: { name: [:admin, :manager] })

但我怎样才能找到至少拥有以下内容的所有用户:admin AND:manager roles?

4 个答案:

答案 0 :(得分:1)

这是一个有效的解决方案:

User.select("DISTINCT users.*").
  joins("JOIN users_roles a ON a.user_id = users.id").
  joins("JOIN roles b ON b.id = a.role_id").
  joins("JOIN users_roles c ON c.user_id = users.id").
  joins("JOIN roles d ON d.id = c.role_id").
  where("b.name = ? and d.name = ? ", :admin, :manager)

答案 1 :(得分:1)

这将有效:

users = User.joins(:roles)
users.where("roles.name" => "admin") & users.where("roles.name" => "manager")

请注意,这会产生两个SQL加载查询,我认为这种类型的搜索可能是不可避免的。 (您的替代解决方案也会进行两次SQL查询。)另请注意,它返回一个数组而不是一个activerecord关系,这可能不是您想要的。

答案 2 :(得分:0)

这有效但感觉不对:

Role.where(name: :admin).first.users.joins(:roles).where(roles: { name: :manager } )

答案 3 :(得分:0)

如果您将关联设置为has_many :through,则可以按用户计算唯一角色:

class User < ActiveRecord::Base
  has_many :user_roles
  has_many :roles, :through => :user_roles
end

# Note: add an id column on the join table
class UserRole < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
end

class Role < ActiveRecord::Base
  has_many :user_roles
  has_many :users, :through => :user_roles
end


User.joins(:user_roles => :role).
  select("users.*, COUNT(DISTINCT user_roles.id) as user_role_count").
  where("roles.name IN ('Admin','Manager')").
  group("users.id").
  having("user_role_count = 2")