Как вы делаете orзапрос в Rails 5 ActiveRecord? Кроме того , возможно приковать orс whereв ActiveRecord запросов?
Как вы делаете orзапрос в Rails 5 ActiveRecord? Кроме того , возможно приковать orс whereв ActiveRecord запросов?
Ответы:
Возможность связывать orпредложение вместе с whereпредложением в ActiveRecordзапросе будет доступна в Rails 5 . См. Соответствующее обсуждение и запрос на перенос .
Итак, в Rails 5 вы сможете делать следующее :
Чтобы получить postс id1 или 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"))