Rails ActiveRecord: Найти всех пользователей, кроме текущего пользователя
Я чувствую, что это должно быть очень просто, но мой мозг замыкается на нем. Если у меня есть объект, представляющий текущего пользователя, и вы хотите запросить всех пользователей, кроме текущего пользователя, как я могу это сделать, учитывая, что текущий пользователь может иногда быть nil
?
Вот что я делаю прямо сейчас:
def index
@users = User.all
@users.delete current_user
end
Мне не нравится то, что я делаю пост-обработку результата запроса. Кроме того, чувствуя себя немного не так, я не думаю, что это будет хорошо работать, если я конвертирую запрос на запуск с will_paginate
. Любые предложения по тому, как это сделать с запросом? Спасибо.
Ответы
Ответ 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 в [], чтобы вставить его в массив.