Wie machst du ein or
Abfrage in Rails 5 ActiveRecord durch? Auch ist es möglich, Kette or
mit where
in Active abfragt?
Wie machst du ein or
Abfrage in Rails 5 ActiveRecord durch? Auch ist es möglich, Kette or
mit where
in Active abfragt?
Antworten:
Die Möglichkeit, or
Klauseln zusammen mit where
Klauseln in ActiveRecord
Abfragen zu verketten, ist in Rails 5 verfügbar . Siehe die zugehörige Diskussion und die Pull-Anfrage .
In Rails 5 können Sie also Folgendes tun :
So erhalten Sie eine post
mit id
1 oder 2:
Post.where('id = 1').or(Post.where('id = 2'))
Einige andere Beispiele:
(A && B) || C:
Post.where(a).where(b).or(Post.where(c))
(A || B) && C:
Post.where(a).or(Post.where(b)).where(c)
Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d)))
dies (a || b) && (c || d)
ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Wir müssen nicht auf Schienen 5 warten, um diese OR
Abfrage zu verwenden. Wir können es auch mit verwenden rails 4.2.3
. Es gibt eine Rückportierung hier .
Vielen Dank an Eric-Guo für das Juwel wo-oder . Jetzt können wir diese OR
Funktionalität hinzufügen, >= rails 4.2.3
indem wir dieses Juwel auch verwenden.
Ich musste eine machen (A && B) || (C && D) || (E && F)
Aber in Rails 5.1.4
'aktuellem Zustand ist dies zu kompliziert, um es mit der Arel-Kette zu erreichen. Aber ich wollte immer noch Rails verwenden, um so viel Abfrage wie möglich zu generieren.
Also habe ich einen kleinen Hack gemacht:
In meinem Modell habe ich eine private Methode namens erstellt sql_where
:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
Als nächstes habe ich in meinem Bereich ein Array erstellt, das die OPs enthält
scope :whatever, -> {
ors = []
ors << sql_where(A, B)
ors << sql_where(C, D)
ors << sql_where(E, F)
# Now just combine the stumps:
where(ors.join(' OR '))
}
Welches wird das erwartete Abfrageergebnis erzeugen :
SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F))
.
Und jetzt kann ich dies problemlos mit anderen Bereichen usw. kombinieren, ohne dass es zu falschen OPs kommt.
Das Schöne ist, dass mein sql_where normale where-Klausel-Argumente verwendet:
sql_where(name: 'John', role: 'admin')
generiert (name = 'John' AND role = 'admin')
.
.merge
das Äquivalent von && verwenden und einen geeigneten Baum erstellen, um Ihre Eltern zu erfassen. Etwas wie ... (scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))
, vorausgesetzt, jeder der Bereiche sieht Model.where(...)
Schienen 5 hat die Fähigkeit zur or
Klausel mit where
. Beispielsweise.
User.where(name: "abc").or(User.where(name: "abcd"))