web-dev-qa-db-de.com

Schienen 5: ActiveRecord OR Abfrage

Wie führt man eine or-Abfrage in Rails 5 ActiveRecord durch? Kann or auch mit where in ActiveRecord-Abfragen verkettet werden?

94

Die Möglichkeit, or-Klausel zusammen mit where-Klausel in ActiveRecord-Abfrage zu verketten, ist in Rails 5 verfügbar. Siehe verwandte Diskussion und Pull-Anforderung .

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)
192

Wir müssen nicht darauf warten, dass Rails 5 diese OR-Abfrage verwendet. Wir können es auch mit Rails 4.2.3 verwenden. Es gibt einen Backport hier .

Dank Eric-Guo für gem where-or , Jetzt können wir diese OR-Funktionalität in >= Rails 4.2.3 auch unter Verwendung dieses Gems hinzufügen.

12
Dipak Gupta

Ich musste einen(A && B) || (C && D) || (E && F)machen

Im aktuellen Stand von Rails 5.1.4 ist dies jedoch zu kompliziert, um es mit der Arel-Kette zu erreichen ..__ Ich wollte trotzdem Rails verwenden, um so viel wie möglich von der Abfrage zu generieren.

Also habe ich einen kleinen Hack gemacht:

In meinem Modell habe ich eine private -Methode mit dem Namen sql_where erstellt:

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, in dem die ODERs enthalten sind

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 '))
}

Daraus ergibt sich das erwartete Abfrageergebnis: 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 falsche ODERs.

Die Schönheit ist, dass meine sql_where normale Argumente für Where-Klauseln verwendet: sql_where(name: 'John', role: 'admin') generiert (name = 'John' AND role = 'admin').

4
mtrolle

(Nur eine Ergänzung zur Antwort von M Rakibul Islam.)

Mit Hilfe von Scopes kann der Code (je nach den Augen) hübscher werden:

scope a,      -> { where(a) }
scope b,      -> { where(b) }

scope a_or_b, -> { a.or(b) }
3
Nicholas

Rails 5 kann or-Klausel mit where.

User.where(name: "abc").or(User.where(name: "abcd"))
0
Foram Thakral