Rails ActiveRecord: Find All Users Except Current User

Ruby on-RailsRubyActiverecord

Ruby on-Rails Problem Overview


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.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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.

Solution 2 - Ruby on-Rails

@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))

Solution 3 - Ruby on-Rails

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.

Solution 4 - Ruby on-Rails

Here is a shorter version:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])

Solution 5 - Ruby on-Rails

One note on GhandaL's answer - at least in Rails 3, it's worth modifying to

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

(the primary change here is from 'id != ...' to 'users.id !=...'; also scope instead of named_scope for Rails 3)

The original version works fine when simply scoping the Users table. When applying the scope to an association (e.g. team.members.without_user(current_user).... ), this change was required to clarify which table we're using for the id comparison. I saw a SQL error (using SQLite) without it.

Apologies for the separate answer...i don't yet have the reputation to comment directly on GhandaL's answer.

Solution 6 - Ruby on-Rails

Very easy solution I used

@users = User.all.where("id != ?", current_user.id)

Solution 7 - Ruby on-Rails

User.all.where("id NOT IN(?)", current_user.id) will through exception undefined method where for #<Array:0x0000000aef08f8>

User.where("id NOT IN (?)", current_user.id)

Solution 8 - Ruby on-Rails

Another easy way you could do it:

@users = User.all.where("id NOT IN(?)", current_user.id)

Solution 9 - Ruby on-Rails

an array would be more helpful

arrayID[0]=1

arrayID[1]=3

User.where.not(id: arrayID)

Solution 10 - Ruby on-Rails

User.where(:id.ne=> current_user.id)

Solution 11 - Ruby on-Rails

ActiveRecord::QueryMethods#excluding (Rails 7+)


Starting from Rails 7, there is a new method ActiveRecord::QueryMethods#excluding.

A quote right from the official Rails docs:

> excluding(*records)

> Excludes the specified record (or collection of records) from the resulting relation. For example:

Post.excluding(post)
# SELECT "posts".* FROM "posts" WHERE "posts"."id" != 1

Post.excluding(post_one, post_two)
# SELECT "posts".* FROM "posts" WHERE "posts"."id" NOT IN (1, 2)

> This can also be called on associations. As with the above example, either a single record of collection thereof may be specified:

post = Post.find(1)
comment = Comment.find(2)
post.comments.excluding(comment)
# SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 AND "comments"."id" != 2

> This is short-hand for .where.not(id: post.id) and .where.not(id: [post_one.id, post_two.id]).

> An ArgumentError will be raised if either no records are specified, or if any of the records in the collection (if a collection is passed in) are not instances of the same model that the relation is scoping.

> Also aliased as: without


Sources:

Solution 12 - Ruby on-Rails

What you are doing is deleting the current_user from the @users Array. This won't work since there isn't a delete method for arrays. What you probably want to do is this

def index
  @users = User.all
  @users - [current_user]
end

This will return a copy of the @users array, but with the current_user object removed (it it was contained in the array in the first place.

Note: This may not work if array subtraction is based on exact matches of objects and not the content. But it worked with strings when I tried it. Remember to enclose current_user in [] to force it into an Array.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSingleShotView Question on Stackoverflow
Solution 1 - Ruby on-RailsMohamadView Answer on Stackoverflow
Solution 2 - Ruby on-RailsjdlView Answer on Stackoverflow
Solution 3 - Ruby on-RailsJakub KosińskiView Answer on Stackoverflow
Solution 4 - Ruby on-RailsHarish ShettyView Answer on Stackoverflow
Solution 5 - Ruby on-RailsSteve BourneView Answer on Stackoverflow
Solution 6 - Ruby on-RailsPhil DuffneyView Answer on Stackoverflow
Solution 7 - Ruby on-Railsuser3202320View Answer on Stackoverflow
Solution 8 - Ruby on-RailsCeeJey OfficialView Answer on Stackoverflow
Solution 9 - Ruby on-RailsAsif AlamView Answer on Stackoverflow
Solution 10 - Ruby on-RailsLana KushnirView Answer on Stackoverflow
Solution 11 - Ruby on-RailsMarian13View Answer on Stackoverflow
Solution 12 - Ruby on-RailsFotiosView Answer on Stackoverflow