Rails ActiveRecord: Найти всех пользователей, кроме текущего - PullRequest
57 голосов
/ 20 апреля 2010

Я чувствую, что это должно быть очень просто, но мой мозг от этого коротко замыкается. Если у меня есть объект, представляющий текущего пользователя, и я хочу сделать запрос для всех пользователей, кроме текущего, как я могу это сделать, учитывая, что текущим пользователем иногда может быть nil?

Вот что я сейчас делаю:

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

Что мне не нравится, так это то, что я выполняю постобработку результата запроса. Кроме того, что я чувствую себя немного неправильно, я не думаю, что это будет хорошо работать, если я преобразую запрос для запуска с will_paginate. Любые предложения о том, как сделать это с помощью запроса? Спасибо.

Ответы [ 11 ]

136 голосов
/ 10 июля 2013

В 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)

См. where.not() в API Документах .

32 голосов
/ 20 апреля 2010
@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))
16 голосов
/ 20 апреля 2010

Вы также можете создать named_scope, например, в вашей модели:

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

и в контроллере:

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

Эта область будет возвращать всех пользователей при вызове с nil и всех пользователей, кроме указанных в параметре в другом случае. Преимущество этого решения состоит в том, что вы можете связать этот вызов с другими именованными областями или методом will_paginate paginate.

7 голосов
/ 20 апреля 2010

Вот более короткая версия:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])
6 голосов
/ 28 сентября 2011

Одна заметка об ответе GhandaL - по крайней мере, в Rails 3 стоит изменить на

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

(основное изменение здесь с 'id! = ...' на 'users.id! = ...'; также область вместо named_scope для Rails 3)

Оригинальная версия прекрасно работает, когда просто просматриваете таблицу Users. При применении области действия к ассоциации (например, team.members.without_user (current_user) ....), это изменение было необходимо, чтобы уточнить, какую таблицу мы используем для сравнения идентификаторов. Я видел ошибку SQL (с использованием SQLite) без нее.

Извиняюсь за отдельный ответ ... У меня пока нет репутации, чтобы комментировать ответ GhandaL.

2 голосов
/ 20 декабря 2015

Очень простое решение, которое я использовал

@users = User.all.where("id != ?", current_user.id)
1 голос
/ 11 июля 2016

User.all.where ("id NOT IN (?)", Current_user.id) будет через исключение неопределенный метод где для #<Array:0x0000000aef08f8>

User.where("id NOT IN (?)", current_user.id)
0 голосов
/ 26 июня 2018

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

0 голосов
/ 03 июня 2017

массив будет более полезным

arrayID [0] = 1

arrayID [1] = 3

User.where.not (id: arrayID)

0 голосов
/ 04 июля 2016

Еще один простой способ сделать это:

@users = User.all.where("id NOT IN(?)", current_user.id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...