it-roy-ru.com

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

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

Вот чем я сейчас занимаюсь:

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

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

57
SingleShot

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

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

Вы также можете создать 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.

16
Jakub Kosiński

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

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

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

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

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

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

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

6
Steve Bourne

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

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

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

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

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

0
Lana Kushnir

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

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

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

arrayID [0] = 1

arrayID [1] = 3

User.where.not (id: arrayID)

0
Asif Alam