Wie machst du ein or Abfrage in Rails 5 ActiveRecord durch? Auch ist es möglich, Kette ormit wherein Active abfragt?
Wie machst du ein or Abfrage in Rails 5 ActiveRecord durch? Auch ist es möglich, Kette ormit wherein Active abfragt?
Antworten:
Die Möglichkeit, orKlauseln zusammen mit whereKlauseln in ActiveRecordAbfragen 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 postmit id1 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 ORAbfrage 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 ORFunktionalität hinzufügen, >= rails 4.2.3indem 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').
.mergedas Ä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 orKlausel mit where. Beispielsweise.
User.where(name: "abc").or(User.where(name: "abcd"))