Rails的ActiveRecord:查找除当前用户以外的所有用户

我觉得这应该很简单,但是我的大脑在短路。 如果我有一个代表当前用户的对象,并且想要查询除​​当前用户以外的所有用户,那么考虑到当前用户有时可能是nil ,我该怎么做呢?

这就是我现在正在做的事情:

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

我不喜欢的是我正在做查询结果的后处理。 除了感觉有点不对,我不认为这将很好地工作,如果我把查询转换为与will_paginate运行。 任何build议如何使用查询做到这一点? 谢谢。

在Rails 4中可以做到以下几点:

 User.where.not(id: id) 

你可以把它包在一个很好的范围内。

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

或者,如果您愿意,可以使用类方法:

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

这两种方法都会返回一个AR关系对象。 这意味着你可以链接方法调用:

 @users = User.all_except(current_user).paginate 

您可以排除任何数量的用户,因为where()也接受数组。

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

例如:

 @users = User.all_except(User.unverified) 

甚至通过其他协会:

 class Post < ActiveRecord::Base has_many :comments has_many :commenters, -> { uniq }, through: :comments end @commenters = @post.commenters.all_except(@post.author) 

请参阅API文档中的where.not()

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

你也可以创buildnamed_scope,例如在你的模型中:

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

并在控制器中:

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

这个范围将返回所有的用户,当用nil和所有的用户调用,除了在其他情况下给出的参数。 这个解决scheme的优点是你可以自由地链接这个调用与其他命名范围或will_paginate分页方法。

这是一个较短的版本:

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

关于GhandaL的回答 – 至less在Rails 3中,值得修改

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

(这里主要的改变是从'id!= …'改为'users.id!= …'; Rails 3也改用了scope而不是named_scope)

原始版本仅在对Users表进行作用域时可以正常工作。 将范围应用到关联(例如,team.members.without_user(current_user)….)时,需要进行此更改以明确我们用于id比较的表。 我看到一个SQL错误(使用SQLite)没有它。

对于单独的答案道歉…我还没有名誉直接评论GhandaL的答案。

我用的非常简单的解决scheme

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

另一个简单的方法可以做到这一点:

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

User.all.where(“id NOT IN(?)”,current_user.id)会通过exceptionundefined方法,其中#<Array:0x0000000aef08f8>

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

一个数组将会更有帮助

的ArrayID [0] = 1

的ArrayID [1] = 3

User.where.not(id:arrayID)

你正在做的是从@users数组中删除current_user。 这不起作用,因为没有数组的删除方法。 你可能想要做的是这个

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

这将返回一个@users数组的副本,但是会移除current_user对象(它首先被包含在数组中。

注意:如果数组减法是基于对象的精确匹配而不是内容,则这可能不起作用。 但是,当我尝试它时,它使用了string。 请记住将current_user放在[]中以将其强制到数组中。