Schienenmodell finden wo nicht gleich


127

Wie kann ich Datensätze in meiner Datenbank unter nicht gleichen Bedingungen finden? Ich habe das jetzt, aber gibt es eine ausgefallene Art, es zu tun?

GroupUser.where('user_id != ?',me)

Was Sie haben, ist so ziemlich eine gute Rails 3-Methode, denke ich.
Spyros

Antworten:


228

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

GroupUser.where.not(user_id: me)

In Rails 3.x.

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

Um die Länge zu verkürzen, können Sie GroupUser.arel_tablein einer Variablen speichern oder bei Verwendung innerhalb des Modells GroupUserselbst, z. B. in a scope, arel_table[:user_id]anstelle von verwendenGroupUser.arel_table[:user_id]

Rails 4.0-Syntax wird der Antwort von @ jbearden gutgeschrieben


Was ist mit in Vereinen? - has_many: group_users, -> {where.not (status: "Declined")}, through :: groups, Foreign_key: "user_id"
Ajbraus

4
Als Randnotiz funktioniert es auch gut verkettet:GroupUser.where(other_condition: true).where.not(user_id: user_id)
Enrico Carlesso


26

Die einzige Möglichkeit, es schicker zu machen, ist mit MetaWhere .

MetaWhere hat einen neueren Cousin namens Squeel, der Code wie diesen zulässt:

GroupUser.where{user_id != me}

Es versteht sich von selbst, dass es sich nicht lohnt, einen Edelstein zu verwenden, wenn dies der einzige Refaktor ist, den Sie herstellen werden, und ich würde einfach bei dem bleiben, was Sie haben. Squeel ist nützlich in Situationen, in denen viele komplexe Abfragen mit Ruby-Code interagieren.


4
MetaWhere ist großartig, aber diese Aufgabe kann ohne Hinzufügen eines Edelsteins ausgeführt werden.
tybro0103

1
@ tybro0103 Natürlich kann die Aufgabe erledigt werden (und imho ist die Art und Weise, wie das OP es macht, vollkommen in Ordnung), die Frage ist, ob man es schicker machen soll. Wenn Sie also glauben, dass es ohne Edelstein schicker gemacht werden kann, würde mich sehr interessieren, wie das geht.
Jakub Hampl

Vikrants Antwort liefert eine Lösung, die weder SQL noch ein anderes Juwel beinhaltet. Aber ich stehe korrigiert da, Ihre Antwort ist definitiv die kodiererfreundlichste / ausgefallenste.
tybro0103

1
Hinzufügen eines Edelsteins, um eine so einfache Aufgabe zu erfüllen. Schlagen eines Mozzy mit einer Panzerfaust
baash05

Das ist übertrieben.
Courtsimas

22

Schienen 4:

Wenn Sie sowohl ungleich als auch gleich verwenden möchten , können Sie Folgendes verwenden:

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

(. Das heißt , wenn Sie eine Vielzahl von Operatoren verwenden möchten >, <), an einem gewissen Punkt können Sie Notationen der folgenden wechseln:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)

Was ist mit GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Enrico Carlesso

@EnricoCarlesso Danke fürs posten. Ich habe meine Antwort aktualisiert, um Ihren Vorschlag aufzunehmen. Vielen Dank.
Rick Smith

9

Sie sollten den Tabellennamen immer in die SQL-Abfrage aufnehmen, wenn Sie sich mit Zuordnungen befassen.

Wenn eine andere Tabelle die user_idSpalte enthält und Sie beide Tabellen verbinden, haben Sie in der SQL-Abfrage einen mehrdeutigen Spaltennamen (dh Probleme).

Also, in Ihrem Beispiel:

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

Oder etwas ausführlicher:

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

Beachten Sie, dass Sie sich darüber keine Gedanken machen müssen, wenn Sie einen Hash verwenden, da Rails dies für Sie erledigt:

GroupUser.where(user: me)

In Rails 4 wurde, wie von @ dr4k3 angegeben, die Abfragemethode nothinzugefügt:

GroupUser.where.not(user: me)

6

In Rails 3 kenne ich nichts ausgefalleneres. Ich bin mir jedoch nicht sicher, ob Ihre ungleiche Bedingung nicht mit (user_id) NULL-Werten übereinstimmt. Wenn Sie das wollen, müssen Sie so etwas tun:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.