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放在[]中以将其强制到数组中。