Ruby on rails 3 Rails ActiveRecord作用域,即;相反的;属于另一个范围,或用户;“缺乏”;财产

Ruby on rails 3 Rails ActiveRecord作用域,即;相反的;属于另一个范围,或用户;“缺乏”;财产,ruby-on-rails-3,activerecord,scope,named-scope,Ruby On Rails 3,Activerecord,Scope,Named Scope,我有一个user.rb的模型,其中我为管理员定义了一个范围,即通过权限表具有管理员角色的用户 has_many :permissions has_many :roles, :through => :permissions 工作范围如下: scope :admins, joins(:permissions).merge(Permission.admin_permissions) 我还想创建一个名为非管理员或类似的范围,它是所有没有管理员角色的用户 做这件事最简单的方法是什么?一种简单的方

我有一个user.rb的模型,其中我为
管理员
定义了一个范围,即通过权限表具有管理员角色的用户

has_many :permissions
has_many :roles, :through => :permissions
工作范围如下:

scope :admins, joins(:permissions).merge(Permission.admin_permissions)
我还想创建一个名为
非管理员
或类似的范围,它是所有没有管理员角色的用户


做这件事最简单的方法是什么?

一种简单的方法,对于很多用户来说是不可行的:

admin_user_ids  = User.admins.map(&:id)
non_admin_users = User.all.reject { |u| admin_user_ids.include?(u.id) }

如果您想要一个反向SQL查询,您必须自己手动执行。没有内置的ActiveRecord解决方案

scope :admins, joins(:permissions).merge(Permission.where("permissions.admin = true"))
scope :non_admins, joins(:permissions).merge(Permission.where("permissions.admin = false"))

如果有很多作用域或它们是复杂的,考虑用ID:< /P>排除它们。

User.where("id not in (?)", User.admins.pluck(:id))

# or if you are already using admin records
admins = User.admins
User.where("id not in (?)", admins.map(&:id))

根据原始查询的行数和复杂性,这可能比前一种方法慢或快。

第一行的一种更快的方法是执行“admin\u user\u ids=user.admins.pull(:id)”作为范围解决方案,我的问题是,在执行连接和合并时,它将只考虑已创建相关对象的对象。在我的情况下,我不是在处理用户+权限。因此,我需要为所有具有false属性的相关对象的对象以及所有不具有相关属性的对象返回一个集合。你的方式对我不起作用