Comment faire une orrequête dans Rails 5 ActiveRecord? En outre, est-il possible de chaîner oravec des whererequêtes ActiveRecord?
Comment faire une orrequête dans Rails 5 ActiveRecord? En outre, est-il possible de chaîner oravec des whererequêtes ActiveRecord?
Réponses:
La possibilité de chaîner la orclause avec la whereclause dans la ActiveRecordrequê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 postavec id1 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.4l'é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').
.mergecomme é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 orclause avec where. Par exemple.
User.where(name: "abc").or(User.where(name: "abcd"))