64

Я знаю, что есть 3 основные обозначения для подачи аргументов методу where ActiveRecord:ActiveRecord ИЛИ Hash запрос обозначения

  1. Pure Струнный
  2. Массив
  3. Hash

Задание and для where метод является прямым:

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

Задание or для этого же метода where меня превзошел для синтаксиса хэша. Является ли это возможным?

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

ответ

126

Есть 5 вариантов, которые могут рассматриваться в качестве реализаций «Hash нотации» (последние два являются своего рода hash- МОГ):

  1. С Рубином на Rails 5 вы можете сделать следующие цепочки, используя ActiveRecord::Relation#or метод:

    Person.where(name: 'Neil').or(Person.where(age: 27)) 
    
  2. Используйте where_values вместе с reduce. Необходимо использовать метод unscopedonly for Rails 4.1+, чтобы обеспечить, что default_scope не включен в where_values.В противном случае предикаты от обоих default_scope и where будет прикован с or оператора:

    Person.where( 
        Person.unscoped.where(name: ['Neil'], age: [27]).where_values.reduce(:or) 
    ) 
    
  3. установки сторонних плагинов, которые реализуют эти или подобные функции, например:

    • Where Or(портировать из Ruby on Rails 5 .or, указанная выше)

    • 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. Использование Arel:

    Person.where( 
        Person.arel_table[:name].eq('Neil').or(
        Person.arel_table[:age].eq(27) 
    ) 
    ) 
    
  5. Использование подготовленных операторов с именованными параметрами:

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

Это полный ответ. Ответ 'isl' особенно хорош, так как это то, что добавляется к Rails 5, как я понимаю. –

+0

Если вы не можете дождаться Rails 5, вы можете использовать этот backport этой функции для рельсов 4.2. Красиво упакован как «где-либо» gem https://github.com/Eric-Guo/where-or – Rob

+0

Если ваш проект все еще находится в Rails 3+, вы можете попробовать rails_or gem: https: // github. ком/khiav223577/rails_or –

1

Как говорит potashin, вы можете использовать другие сторонние плагины, которые реализуют эту функцию , Я долгое время использовал Squeel и прекрасно работает для этого и гораздо больше функций, таких как сложные подзапросы или объединения.

Этот запрос с использованием squeel:

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