I have a model for user.rb, in which I define a scope for admins
, which is users that have the role of admin through a permissions table.
has_many :permissions
has_many :roles, :through => :permissions
The scope works like this:
scope :admins, joins(:permissions).merge(Permission.admin_permissions)
I'd also like to make a scope called non-admins
or something like that, which is all users that do NOT have the admin role.
What's the easiest way to do this?
An easy way, which would not be performant for a lot of users:
admin_user_ids = User.admins.map(&:id)
non_admin_users = User.all.reject { |u| admin_user_ids.include?(u.id) }
If you want to have an inverted SQL query, you will have to do it yourself manually. There is no built-in ActiveRecord solution.
scope :admins, joins(:permissions).merge(Permission.where("permissions.admin = true"))
scope :non_admins, joins(:permissions).merge(Permission.where("permissions.admin = false"))
If there are a lot of scopes or they are complex, consider excluding them by id:
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))
Depending on number of rows and complexity of the original query, this could be slower or faster than the previous way.