views:

392

answers:

4

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.

+5  A: 
@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))
jdl
A bit more verbose than I was hoping (unavoidable I suspect) but does what I want. Thanks for helping a relative noob :-)
SingleShot
You're welcome. If it were mine, I'd push the "except for current user" logic into a named_scope on the User model. That'll cut down on the verbosity in your controller.
jdl
Thanks for the named_scope suggestion. It did clean up the controller a bit and made it less ugly when "upgrading" to will_paginate. Thanks again.
SingleShot
A: 

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.

Fotios
Thanks for your answer. The code example I submitted does in fact work because there actually is a delete method on Array. Unfortunately your suggestion doesn't quite achieve what I am looking for. Thanks again.
SingleShot
>> Array.new.methods.grep /delete/=> ["delete_at", "delete_if", "delete"]
+3  A: 

Here is a shorter version:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])
KandadaBoggu
I took the answer from user jdl, his comment about named scopes, and your refinement and am now happy. The controller is pretty clean, though the named_scoped is a bit ugly. After adding will_paginate here's my query: User.all_except(current_user).paginate(:page => params[:page])
SingleShot
@SingleShot I have edited the answer.
KandadaBoggu
Looks good to me.
KandadaBoggu
+1  A: 

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.

GhandaL
This is the best answer. Keep data in scopes as long as possible. Also, this is how most queries will work in Rails 3 with Arel.
Gdeglin