Як зробити or
запит у Rails 5 ActiveRecord? Також, чи можливо ланцюжок or
із where
запитами ActiveRecord?
Як зробити or
запит у Rails 5 ActiveRecord? Також, чи можливо ланцюжок or
із where
запитами ActiveRecord?
Відповіді:
Можливість ланцюга or
пункту разом із запитом where
у ActiveRecord
запиті буде доступна в Rails 5 . Дивіться відповідні обговорення та запит на тягнення .
Отже, у Rails 5 ви зможете зробити наступні дії :
Для того, щоб отримати post
з id
1 або 2:
Post.where('id = 1').or(Post.where('id = 2'))
Деякі інші приклади:
(A&& B) || C:
Post.where(a).where(b).or(Post.where(c))
(A || B) & C:
Post.where(a).or(Post.where(b)).where(c)
Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d)))
це повинно створити (a || b) && (c || d)
ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Мені потрібно було зробити (A && B) || (C && D) || (E && F)
Але в 5.1.4
нинішньому стані Рейлівс це стає занадто складним, щоб здійснити його з ланцюгом Arel. Але я все ж хотів використовувати Rails для отримання якомога більшої кількості запитів.
Тому я зробив невеликий злом:
У своїй моделі я створив приватний метод під назвою sql_where
:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
Далі в своєму діапазоні я створив масив для утримання АБО
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 '))
}
Який дасть очікуваний результат запиту:
SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F))
.
І тепер я можу легко поєднувати це з іншими областями тощо без будь-яких протиправних АБО.
Краса полягає в тому, що мій sql_where приймає нормальні аргументи, де-clause:
sql_where(name: 'John', role: 'admin')
генерує (name = 'John' AND role = 'admin')
.
.merge
як еквівалент &&, і побудувати належне дерево, щоб захопити ваші парени. Щось на кшталт ... (scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))
, якщо припустити, що кожна з областей виглядає приблизно такModel.where(...)
Рейки 5 мають можливість для or
пункту where
. Наприклад.
User.where(name: "abc").or(User.where(name: "abcd"))