Antwort

153

Die Fähigkeit zur Kette or Klausel zusammen mit where Klausel in ActiveRecord Abfrage wird in Rails 5 zur Verfügung. Siehe die related discussion and the pull request.

So werden Sie in der Lage sein, die folgenden Dinge in Rails zu tun 5:

Post.where('id = 1').or(Post.where('id = 2')) 

Einige weitere Beispiele:

Um einen post mit id 1 oder 2 zu erhalten

(A & & B) || C:

Post.where(a).where(b).or(Post.where(c)) 

(A || B) & & C:

Post.where(a).or(Post.where(b)).where(c) 
+3

Wie kann ich bekommen (A || B) && (C || D). Ich habe Post.where (a) .oder (Post.where (b)). Where (c) .oder (Post.where (d)) versucht, aber es produziert als: (A || B) && C || D – Imran

+3

@Imran ich glaube es wäre 'Post.where (a) .oder (Post.where (b)). Wo (Post.where (c) .oder (Post.where (d)))' dies sollte erstellen (a || b) && (c || d) – engineersmnky

12

Wir brauchen nicht für Schienen 5 zu warten, um diese OR Abfrage zu verwenden. Wir können es auch mit rails 4.2.3 verwenden. Es gibt einen Backport here.

danken Eric-Guo für gem where-or, Jetzt können wir diese OR Funktionalität in >= rails 4.2.3 auch hinzufügen, dieses Juwel mit.

3

Ich brauchte eine (A && B) || (C && D) || (E && F)

Aber in Rails 5.1.4 ‚s aktuellen Zustand dieses erhalten ist zu kompliziert zu erreichen, mit dem Arel oder Kette zu tun. Aber ich wollte immer noch Rails verwenden, um so viel wie möglich von der Abfrage zu generieren.

Also machte ich einen kleinen Hack:

In meinem Modell hat ich eine private Methode sql_where genannt:

private 
    def self.sql_where(*args) 
    sql = self.unscoped.where(*args).to_sql 
    match = sql.match(/WHERE\s(.*)$/) 
    "(#{match[1]})" 
    end 

nächste in meinem Rahmen ich ein Array erstellt die

der OR zu halten
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 ')) 
} 

Welche 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 leicht mit anderen Bereichen usw. ohne irgendwelche fehlerhaften ORs kombinieren.

Das Schöne ist, dass meine sql_where normalen Where-Klausel-Argumente: sql_where(name: 'John', role: 'admin')(name = 'John' AND role = 'admin') erzeugen wird.