ActiveRecord ODER Abfrage Hash-Notation

73

Ich weiß, dass es drei Hauptnotationen gibt, um der whereActiveRecord-Methode Argumente zu liefern :

  1. Reine Saite
  2. Array
  3. Hash

Die Angabe andfür die whereMethode ist unkompliziert:

# Pure String notation
Person.where("name = 'Neil' AND age = 27")

# Array notation
Person.where(["name = ? AND age = ?", 'Neil', 27])

# Hash notation
Person.where({name: "Neil", age: 27})

Wenn ich orfür dieselbe whereMethode spezifiziere, bin ich für die Hash-Syntax verblüfft . Ist es möglich?

# Pure String notation
Person.where("name = 'Neil' OR age = 27")

# Array notation
Person.where(["name = ? OR age = ?", 'Neil', 27])

# Hash notation DOESN'T WORK
Person.where({name: "Neil" OR age: 27})
Neil
quelle

Antworten:

142

Es gibt 5 Optionen, die als Implementierungen der «Hash-Notation» betrachtet werden könnten (die letzten beiden sind ein bisschen Hash- ish ):

  1. Mit Ruby on Rails 5 können Sie die folgende Verkettung mit der ActiveRecord::Relation#orMethode durchführen:

    Person.where(name: 'Neil').or(Person.where(age: 27))
    
  2. Verwenden Sie where_valueszusammen mit reduce. Die unscopedMethode ist nur für Rails 4.1+ erforderlich , um sicherzustellen , dass sie default_scopenicht in der enthalten ist where_values. Andernfalls werden Prädikate von beiden default_scopeund wheremit dem orOperator verkettet :

    Person.where( 
      Person.unscoped.where(name: ['Neil'], age: [27]).where_values.reduce(:or) 
    )
    
  3. Installieren Sie Plugins von Drittanbietern, die diese oder ähnliche Funktionen implementieren, z.

    • Where Or (Backport der .oroben erwähnten Ruby on Rails 5- Funktion)

    • Squeel

      Person.where{(name == 'Neil') | (age == 27)} 
      
    • RailsOr

      Person.where(name: 'Neil').or(age: 27)
      
    • ActiverecordAnyOf

      Person.where.anyof(name: 'Neil', age: 27)
      
    • SmartTuple

      Person.where(
        (SmartTuple.new(' or ') << {name: 'Neil', age: 27}).compile
      )
      
  4. Verwenden Sie Arel :

    Person.where( 
      Person.arel_table[:name].eq('Neil').or(
        Person.arel_table[:age].eq(27)
      ) 
    )
    
  5. Verwenden Sie vorbereitete Anweisungen mit benannten Parametern:

    Person.where('name = :name or age = :age', name: 'Neil', age: 27)
    
Kali
quelle
1
Dies ist eine vollständige Antwort. Die arelAntwort ist besonders gut, da dies, wie ich verstehe, zu Rails 5 hinzugefügt wird.
Tom Harrison
Wenn Sie nicht auf Rails 5 warten können, können Sie diesen Backport der Funktion für Rails 4.2 verwenden. Schön verpackt als "wo-oder" Juwel github.com/Eric-Guo/where-or
Rob
Wenn sich Ihr Projekt noch in Rails 3+ befindet, können Sie das Juwel
rails_or ausprobieren
1

Wie bereits erwähnt, können Sie andere Plugins von Drittanbietern verwenden, die diese Funktion implementieren. Ich habe lange Zeit mit Squeel gearbeitet und arbeite ziemlich gut für diese und viele weitere Funktionen wie komplexe Unterabfragen oder Verknüpfungen.

Diese Abfrage mit squeel:

@people= Person.where{(name == 'Neil') | (age = 27)}
Antonio Grass
quelle