web-dev-qa-db-fra.com

Rails ActiveRecord: Trouver tous les utilisateurs sauf l'utilisateur actuel

Je pense que cela devrait être très simple mais mon cerveau court-circuite dessus. Si j'ai un objet représentant l'utilisateur actuel et que je souhaite interroger tous les utilisateurs à l'exception de l'utilisateur actuel, comment puis-je procéder, en tenant compte du fait que l'utilisateur actuel peut parfois être nil?

Voici ce que je fais en ce moment:

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

Ce que je n'aime pas, c'est que je fais du post-traitement sur le résultat de la requête. En plus de me sentir un peu dans l'erreur, je ne pense pas que cela fonctionnera bien si je convertis la requête pour qu'elle soit exécutée avec will_paginate. Des suggestions sur la façon de procéder avec une requête? Merci.

56
SingleShot

Il est possible de faire ce qui suit dans Rails 4:

User.where.not(id: id)

Vous pouvez l'envelopper dans un cadre de Nice.

scope :all_except, ->(user) { where.not(id: user) }
@users = User.all_except(current_user)

Ou utilisez une méthode de classe si vous préférez:

def self.all_except(user)
  where.not(id: user)
end

Les deux méthodes renverront un objet de relation AR. Cela signifie que vous pouvez chaîner des appels de méthode:

@users = User.all_except(current_user).paginate

Vous pouvez exclure n'importe quel nombre d'utilisateurs car where() accepte également un tableau.

@users = User.all_except([1,2,3])

Par exemple:

@users = User.all_except(User.unverified)

Et même à travers d'autres associations:

class Post < ActiveRecord::Base
  has_many :comments
  has_many :commenters, -> { uniq }, through: :comments
end

@commenters = @post.commenters.all_except(@post.author)

Voir where.not() dans Documents API .

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

Vous pouvez également créer named_scope, par exemple dans votre modèle:

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

et dans le contrôleur:

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

Cette portée retournera tous les utilisateurs lorsqu'elle sera appelée avec nil et tous les utilisateurs, sauf donnée dans param dans les autres cas. L'avantage de cette solution est que vous êtes libre de chaîner cet appel avec d'autres scopes nommés ou avec la méthode will_paginate paginate.

16
Jakub Kosiński

Voici une version plus courte:

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

Une note sur la réponse de GhandaL - du moins dans Rails 3, il convient de le modifier pour

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

(Le changement principal ici est de 'id! = ...' à 'users.id! = ...'; également à la place de named_scope pour Rails 3)

La version originale fonctionne correctement lorsque vous parcourez simplement la table Users. Lors de l'application de l'étendue à une association (par exemple, team.members.without_user (current_user) ...), cette modification était nécessaire pour préciser la table utilisée pour la comparaison d'identifiant. J'ai vu une erreur SQL (en utilisant SQLite) sans elle.

Toutes mes excuses pour la réponse séparée ... Je n'ai pas encore la réputation de commenter directement la réponse de GhandaL.

6
Steve Bourne

Solution très facile j'ai utilisé

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

User.all.where ("id NOT IN (?)", Current_user.id) passera par l'exception Méthode undefined où pour #<Array:0x0000000aef08f8>

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

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

0
Lana Kushnir

Un autre moyen facile de le faire:

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

un tableau serait plus utile

arrayID [0] = 1

arrayID [1] = 3

User.where.not (id: arrayID)

0
Asif Alam