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

Sin*_*hot 58 ruby activerecord ruby-on-rails

我觉得这应该很简单,但我的大脑正在短路.如果我有表示当前用户的一个对象,并希望查询除了当前用户的所有用户,我怎么能做到这一点,考虑到当前用户有时会nil

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

def index
  @users = User.all
  @users.delete current_user
end
Run Code Online (Sandbox Code Playgroud)

我不喜欢的是我正在对查询结果进行后处理.除了感觉有点不对外,如果我将查询转换为运行,我认为这不会很好will_paginate.有关如何使用查询执行此操作的任何建议?谢谢.

Moh*_*mad 140

可以在Rails 4中执行以下操作:

User.where.not(id: id)
Run Code Online (Sandbox Code Playgroud)

你可以将它包装在一个很好的范围内.

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

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

def self.all_except(user)
  where.not(id: user)
end
Run Code Online (Sandbox Code Playgroud)

两种方法都将返回AR关系对象.这意味着您可以链接方法调用:

@users = User.all_except(current_user).paginate
Run Code Online (Sandbox Code Playgroud)

您可以排除任意数量的用户,因为它where()也接受一个数组.

@users = User.all_except([1,2,3])
Run Code Online (Sandbox Code Playgroud)

例如:

@users = User.all_except(User.unverified)
Run Code Online (Sandbox Code Playgroud)

甚至通过其他协会:

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

@commenters = @post.commenters.all_except(@post.author)
Run Code Online (Sandbox Code Playgroud)

where.not()API文档.


jdl*_*jdl 32

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


Jak*_*ski 16

您也可以创建named_scope,例如在您的模型中:

named_scope :without_user, lambda{|user| user ? {:conditions => ["id != ?", user.id]} : {} }
Run Code Online (Sandbox Code Playgroud)

在控制器中:

def index
  @users = User.without_user(current_user).paginate
end
Run Code Online (Sandbox Code Playgroud)

当使用nil调用时,此范围将返回所有用户,而在其他情况下,除了在param中给出之外的所有用户.此解决方案的优点是您可以自由地将此调用与其他命名范围或will_paginate paginate方法链接.


Har*_*tty 7

这是一个较短的版本:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])
Run Code Online (Sandbox Code Playgroud)


Ste*_*rne 6

关于GhandaL答案的一个注释 - 至少在Rails 3中,它值得修改

scope :without_user, lambda{|user| user ? {:conditions => ["users.id != ?", user.id]} : {} }
Run Code Online (Sandbox Code Playgroud)

(这里的主要变化是从'id!= ...'到'users.id!= ...';也是范围而不是Rails 3的named_scope)

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

为单独答案道歉...我还没有直接评论GhandaL答案的声誉.