ruby-on-rails - framework - tutorial django
Rails ActiveRecord: Buscar todos los usuarios excepto el usuario actual (11)
Siento que esto debería ser muy simple, pero mi cerebro está cortocircuitando en eso. Si tengo un objeto que representa al usuario actual y deseo consultar para todos los usuarios, excepto el usuario actual, ¿cómo puedo hacerlo, teniendo en cuenta que el usuario actual a veces puede ser nil
?
Esto es lo que estoy haciendo en este momento:
def index
@users = User.all
@users.delete current_user
end
Lo que no me gusta es que estoy haciendo post-procesamiento en el resultado de la consulta. Además de sentirme un poco mal, no creo que esto funcione bien si convierto la consulta para que se ejecute con will_paginate
. ¿Alguna sugerencia de cómo hacer esto con una consulta? Gracias.
Aquí hay una versión más corta:
User.all :conditions => (current_user ? ["id != ?", current_user.id] : [])
Es posible hacer lo siguiente en Rails 4:
User.where.not(id: id)
Puedes envolverlo en un buen alcance.
scope :all_except, ->(user) { where.not(id: user) }
@users = User.all_except(current_user)
O use un método de clase si lo prefiere:
def self.all_except(user)
where.not(id: user)
end
Ambos métodos devolverán un objeto de relación AR. Esto significa que puede encadenar llamadas de método:
@users = User.all_except(current_user).paginate
Puede excluir cualquier número de usuarios porque where()
también acepta una matriz.
@users = User.all_except([1,2,3])
Por ejemplo:
@users = User.all_except(User.unverified)
E incluso a través de otras asociaciones:
class Post < ActiveRecord::Base
has_many :comments
has_many :commenters, -> { uniq }, through: :comments
end
@commenters = @post.commenters.all_except(@post.author)
Ver where.not()
en los where() .
Lo que está haciendo es eliminar el usuario_actual de la matriz @users. Esto no funcionará ya que no hay un método de eliminación para las matrices. Lo que probablemente quieras hacer es esto
def index
@users = User.all
@users - [current_user]
end
Esto devolverá una copia de la matriz @users, pero con el objeto current_user eliminado (en primer lugar, estaba contenido en la matriz).
Nota: Esto puede no funcionar si la resta de matriz se basa en coincidencias exactas de objetos y no en el contenido. Pero funcionó con cuerdas cuando lo probé. Recuerde incluir current_user en [] para forzarlo a una matriz.
Otra forma fácil de hacerlo:
@users = User.all.where("id NOT IN(?)", current_user.id)
Solución muy fácil que utilicé
@users = User.all.where("id != ?", current_user.id)
También puede crear named_scope, por ejemplo en su modelo:
named_scope :without_user, lambda{|user| user ? {:conditions => ["id != ?", user.id]} : {} }
y en el controlador:
def index
@users = User.without_user(current_user).paginate
end
Este ámbito devolverá a todos los usuarios cuando se invoque con nil y todos los usuarios excepto en el caso de param en otro caso. La ventaja de esta solución es que puede encadenar esta llamada con otros ámbitos nombrados o con el método will_paginate de paginate.
Una nota sobre la respuesta de GhandaL: al menos en Rails 3, vale la pena modificarlo
scope :without_user, lambda{|user| user ? {:conditions => ["users.id != ?", user.id]} : {} }
(el cambio principal aquí es de ''id! = ...'' a ''users.id! = ...''; también scope en lugar de named_scope para Rails 3)
La versión original funciona bien cuando simplemente se analiza la tabla Usuarios. Al aplicar el alcance a una asociación (por ejemplo, team.members.without_user (current_user) ....), este cambio fue necesario para aclarar qué tabla estamos utilizando para la comparación de id. Vi un error de SQL (usando SQLite) sin él.
Disculpas por la respuesta por separado ... todavía no tengo la reputación de comentar directamente la respuesta de GhandaL.
User.all.where ("id NOT IN (?)", Current_user.id) a través del método de excepción indefinido donde para #<Array:0x0000000aef08f8>
User.where("id NOT IN (?)", current_user.id)
User.where (: id.ne => current_user.id)
una matriz sería más útil
arrayID [0] = 1
arrayID [1] = 3
User.where.not (id: arrayID)
@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))