Как вы делаете 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
текущем состоянии Rails это слишком сложно сделать с помощью Arel or-chain. Но я по-прежнему хотел использовать Rails для генерации как можно большего количества запросов.
Итак, я сделал небольшой взлом:
В моей модели я создал частный метод под названием sql_where
:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
Затем в своей области я создал массив для хранения OR
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 принимает обычные аргументы 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(...)
В Rails 5 есть возможность использовать or
предложения where
. Например.
User.where(name: "abc").or(User.where(name: "abcd"))