ActiveRecord OR query Hash notation

Ruby on-RailsRuby on-Rails-4ActiverecordRails ActiverecordRuby on-Rails-5

Ruby on-Rails Problem Overview


I know there are 3 main notations for supplying arguments to the where ActiveRecord method:

  1. Pure String
  2. Array
  3. Hash

Specifying and for the where method is straight forward:

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

Specifying or for this same where method is stumping me for the hash syntax. Is it possible?

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

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

There are 5 options that could be considered as implementations of «Hash notation» (the last two are kinda hash-ish):

  1. With Ruby on Rails 5 you are able to do the following chaining using ActiveRecord::Relation#or method:

     Person.where(name: 'Neil').or(Person.where(age: 27))
    
  2. Use where_values together with reduce. The unscoped method is necessary only for Rails 4.1+ to ensure default_scope is not included in the where_values. Otherwise predicates from both default_scope and where would be chained with the or operator:

     Person.where( 
       Person.unscoped.where(name: ['Neil'], age: [27]).where_values.reduce(:or) 
     )
    
  3. Install third-party plugins that implement these or similar features, for example:

  • Where Or (backport of the Ruby on Rails 5 .or feature mentioned above)

  • 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
          )
    
  1. Use Arel:

     Person.where( 
       Person.arel_table[:name].eq('Neil').or(
         Person.arel_table[:age].eq(27)
       ) 
     )
    
  2. Use prepared statements with named parameters:

     Person.where('name = :name or age = :age', name: 'Neil', age: 27)
    

Solution 2 - Ruby on-Rails

As says potashin, you can use another third-party plugins that implement this feature. I have a long time using Squeel and works pretty well for this and much more features like complex subqueries or joins.

That query using squeel:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNeilView Question on Stackoverflow
Solution 1 - Ruby on-RailspotashinView Answer on Stackoverflow
Solution 2 - Ruby on-RailsAntonio GrassView Answer on Stackoverflow