Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ActiveRecord: Find All Users Except Current User

I feel this should be very simple but my brain is short-circuiting on it. If I have an object representing the current user, and want to query for all users except the current user, how can I do this, taking into account that the current user can sometimes be nil?

This is what I am doing right now:

def index
  @users = User.all
  @users.delete current_user
end

What I don't like is that I am doing post-processing on the query result. Besides feeling a little wrong, I don't think this will work nicely if I convert the query over to be run with will_paginate. Any suggestions for how to do this with a query? Thanks.

like image 426
SingleShot Avatar asked Apr 20 '10 05:04

SingleShot


4 Answers

It is possible to do the following in Rails 4 and up:

User.where.not(id: id)

You can wrap it in a nice scope.

scope :all_except, ->(user) { where.not(id: user) }
@users = User.all_except(current_user)

Or use a class method if you prefer:

def self.all_except(user)
  where.not(id: user)
end

Both methods will return an AR relation object. This means you can chain method calls:

@users = User.all_except(current_user).paginate

You can exclude any number of users because where() also accepts an array.

@users = User.all_except([1,2,3])

For example:

@users = User.all_except(User.unverified)

And even through other associations:

class Post < ActiveRecord::Base
  has_many :comments
  has_many :commenters, -> { uniq }, through: :comments
end

@commenters = @post.commenters.all_except(@post.author)

See where.not() in the API Docs.

like image 76
Mohamad Avatar answered Sep 20 '22 13:09

Mohamad


@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))
like image 26
jdl Avatar answered Sep 20 '22 13:09

jdl


You can also create named_scope, e.g. in your model:

named_scope :without_user, lambda{|user| user ? {:conditions => ["id != ?", user.id]} : {} }

and in controller:

def index
  @users = User.without_user(current_user).paginate
end

This scope will return all users when called with nil and all users except given in param in other case. The advantage of this solution is that you are free to chain this call with other named scopes or will_paginate paginate method.

like image 16
Jakub Kosiński Avatar answered Sep 21 '22 13:09

Jakub Kosiński


Here is a shorter version:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])
like image 7
Harish Shetty Avatar answered Sep 19 '22 13:09

Harish Shetty