Como você faz uma or
consulta no Rails 5 ActiveRecord? Além disso, é possível a cadeia or
com where
no ActiveRecord consultas?
Como você faz uma or
consulta no Rails 5 ActiveRecord? Além disso, é possível a cadeia or
com where
no ActiveRecord consultas?
Respostas:
A capacidade de encadear or
cláusula junto com a where
cláusula na ActiveRecord
consulta estará disponível no Rails 5 . Veja a discussão relacionada e a solicitação de pull .
Então, você será capaz de fazer as seguintes coisas no Rails 5 :
Para obter um post
com id
1 ou 2:
Post.where('id = 1').or(Post.where('id = 2'))
Alguns outros exemplos:
(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)))
isso deve criar (a || b) && (c || d)
ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Eu precisava fazer um (A && B) || (C && D) || (E && F)
Mas no 5.1.4
estado atual de Rails , isso é muito complicado de se realizar com o Arel ou cadeia. Mas eu ainda queria usar o Rails para gerar o máximo de consulta possível.
Então, fiz um pequeno hack:
No meu modelo, criei um método privado chamado sql_where
:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
Em seguida, no meu escopo, criei uma matriz para conter os 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 '))
}
Que irá produzir o resultado da consulta esperado:
SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F))
.
E agora posso facilmente combinar isso com outros osciloscópios, etc., sem nenhum OR incorreto.
A beleza é que meu sql_where aceita argumentos normais da cláusula where:
sql_where(name: 'John', role: 'admin')
will generate (name = 'John' AND role = 'admin')
.
.merge
como o equivalente a && e construir uma árvore adequada para capturar seus parênteses. Algo como ... (scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))
, supondo que cada um dos escopos se pareça comModel.where(...)
Rails 5 tem capacidade para or
cláusula com where
. Por exemplo.
User.where(name: "abc").or(User.where(name: "abcd"))