Rails Model trouver où pas égal

127

Comment puis-je trouver des enregistrements dans ma base de données dans une condition différente? Je l'ai maintenant, mais y a-t-il une façon sophistiquée de le faire?

GroupUser.where('user_id != ?',me)
Colin
la source
Ce que vous avez est à peu près une bonne façon de faire Rails 3, je pense.
Spyros

Réponses:

229

Dans Rails 4.x (voir http://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

Dans Rails 3.x

GroupUser.where(GroupUser.arel_table[:user_id].not_eq(me))

Pour raccourcir la longueur, vous pouvez stocker GroupUser.arel_tabledans une variable ou si vous utilisez à l'intérieur du modèle GroupUserlui-même, par exemple, dans a scope, vous pouvez utiliser à la arel_table[:user_id]place deGroupUser.arel_table[:user_id]

Crédit de syntaxe Rails 4.0 à la réponse de @ jbearden

Vikrant Chaudhary
la source
Et dans les associations? - has_many: group_users, -> {where.not (status: "Declined")}, through:: groups, Foreign_key: "user_id"
ajbraus
4
En remarque, cela fonctionne également bien enchaîné:GroupUser.where(other_condition: true).where.not(user_id: user_id)
Enrico Carlesso
38

Rails 4

GroupUser.where.not(user_id: me)
jbearden
la source
26

La seule façon de le rendre plus sophistiqué est avec MetaWhere .

MetaWhere a un cousin plus récent qui s'appelle Squeel qui permet un code comme celui-ci:

GroupUser.where{user_id != me}

Il va sans dire que si c'est le seul refactor que vous allez faire, cela ne vaut pas la peine d'utiliser une gemme et je m'en tiendrai simplement à ce que vous avez. Squeel est utile dans les situations où de nombreuses requêtes complexes interagissent avec le code Ruby.

Jakub Hampl
la source
4
MetaWhere est génial, mais cette tâche peut être effectuée sans ajouter de gemme.
tybro0103
1
@ tybro0103 bien sûr, la tâche peut être effectuée (et à mon avis, la façon dont l'OP le fait est parfaitement bien), la question est de la faire plus sophistiquée. Donc, si vous pensez que cela peut être fait plus sophistiqué sans bijou, je serais très intéressé de savoir comment le faire.
Jakub Hampl
La réponse de Vikrant fournit une solution n'impliquant pas SQL ni une autre gemme. Mais, je reste corrigé, votre réponse est certainement la plus conviviale / la plus sophistiquée pour les codeurs.
tybro0103
1
ajouter un bijou pour accomplir une tâche aussi simple. Frapper un mozzy avec un bazooka
baash05
C'est exagéré.
courtsimas
23

Rails 4:

Si vous souhaitez utiliser à la fois non égal et égal, vous pouvez utiliser:

user_id = 4
group_id = 27
GroupUser.where(group_id: group_id).where.not(user_id: user_id)

Si vous souhaitez utiliser une variété d'opérateurs (c'est-à-dire. >, <), À un moment donné, vous voudrez peut-être changer les notations comme suit:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)
Rick Smith
la source
Et quoi GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Enrico Carlesso
@EnricoCarlesso Merci d'avoir posté. J'ai mis à jour ma réponse pour inclure votre suggestion. Merci.
Rick Smith
9

Vous devez toujours inclure le nom de la table dans la requête SQL lorsque vous traitez des associations.

En effet si une autre table a la user_idcolonne et que vous joignez les deux tables, vous aurez un nom de colonne ambigu dans la requête SQL (c'est-à-dire des problèmes).

Donc, dans votre exemple:

GroupUser.where("groups_users.user_id != ?", me)

Ou un peu plus bavard:

GroupUser.where("#{table_name}.user_id IS NOT ?", me)

Notez que si vous utilisez un hachage, vous n'avez pas à vous en soucier car Rails s'en charge pour vous:

GroupUser.where(user: me)

Dans Rails 4, comme indiqué par @ dr4k3, la méthode de requête nota été ajoutée:

GroupUser.where.not(user: me)
Damien
la source
6

Dans Rails 3, je ne connais rien de plus sophistiqué. Cependant, je ne sais pas si vous êtes au courant, votre condition non égale ne correspond pas aux valeurs NULL (user_id). Si vous voulez cela, vous devrez faire quelque chose comme ceci:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
Konyak
la source