Comment faire une or
requête dans Rails 5 ActiveRecord? En outre, est-il possible de chaîner or
avec des where
requêtes ActiveRecord?
Comment faire une or
requête dans Rails 5 ActiveRecord? En outre, est-il possible de chaîner or
avec des where
requêtes ActiveRecord?
Réponses:
La possibilité de chaîner la or
clause avec la where
clause dans la ActiveRecord
requête sera disponible dans Rails 5 . Voir la discussion associée et la demande d'extraction .
Ainsi, vous pourrez effectuer les opérations suivantes dans Rails 5 :
Pour obtenir un post
avec id
1 ou 2:
Post.where('id = 1').or(Post.where('id = 2'))
Quelques autres exemples:
(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)))
cela devrait créer (a || b) && (c || d)
ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
J'avais besoin de faire un (A && B) || (C && D) || (E && F)
Mais dans 5.1.4
l'état actuel de Rails , cela est trop compliqué à accomplir avec la chaîne ou Arel. Mais je voulais toujours utiliser Rails pour générer autant de requêtes que possible.
J'ai donc fait un petit hack:
Dans mon modèle, j'ai créé une méthode privée appelée sql_where
:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
Ensuite, dans mon champ d'application, j'ai créé un tableau pour contenir les 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 '))
}
Ce qui produira le résultat de la requête prévue:
SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F))
.
Et maintenant, je peux facilement combiner cela avec d'autres portées, etc. sans aucun OR erroné.
La beauté étant que mon sql_where prend des arguments normaux de clause where:
sql_where(name: 'John', role: 'admin')
générera (name = 'John' AND role = 'admin')
.
.merge
comme équivalent de &&, et construire un arbre approprié pour capturer vos parents. Quelque chose comme ... (scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))
, en supposant que chacune des portées ressemble à quelque chose commeModel.where(...)
Rails 5 a la capacité de or
clause avec where
. Par exemple.
User.where(name: "abc").or(User.where(name: "abcd"))