Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Ответ 5

Одна нота в ответе 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)....) это изменение потребовалось, чтобы уточнить, какую таблицу мы используем для сравнения id. Я видел ошибку SQL (используя SQLite) без нее.

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

User.all.where( "id NOT IN (?)", current_user.id) через исключение undefined, где для #<Array:0x0000000aef08f8>

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

Ответ 9

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

arrayID [0] = 1

arrayID [1] = 3

User.where.not(id: arrayID)

Ответ 10

Что вы делаете, это удаление current_user из массива @users. Это не будет работать, поскольку для массивов не существует метода удаления. Что вы, вероятно, захотите сделать, это

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

Это вернет копию массива @users, но с удаленным объектом current_user (вначале он содержался в массиве.

Примечание. Это может не работать, если вычитание массива основано на точном совпадении объектов, а не содержимого. Но он работал со строками, когда я это пробовал. Не забудьте включить current_user в [], чтобы вставить его в массив.