Comment faites-vous une requête or
dans Rails 5 ActiveRecord? De même, est-il possible de chaîner or
avec where
dans les requêtes ActiveRecord?
La possibilité de chaîner la clause or
avec la clause where
dans la requête ActiveRecord
sera disponible dans Rails 5. Voir la discussion connexe et la demande d'extraction .
Ainsi, vous pourrez faire les choses suivantes dans Rails 5:
Pour obtenir une 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)
Je devais faire un(A && B) || (C && D) || (E && F)
Mais dans l'état actuel de Rails 5.1.4
, cela est trop compliqué à accomplir avec Arel ou la chaîne . Mais je voulais tout de même utiliser Rails pour générer autant de requêtes que possible.
Alors j'ai fait un petit bidouillage:
Dans mon modèle, j'ai créé une méthode private 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
Suivant dans ma portée, j'ai créé un tableau pour contenir les blocs
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 requête attendu: 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 OU injustifié.
La beauté est que mon sql_where prend les arguments normaux de la clause where: sql_where(name: 'John', role: 'admin')
générera (name = 'John' AND role = 'admin')
.
(Juste un ajout à la réponse de K M Rakibul Islam.)
En utilisant des oscilloscopes, le code peut devenir plus joli (en fonction de l'aspect des yeux):
scope a, -> { where(a) }
scope b, -> { where(b) }
scope a_or_b, -> { a.or(b) }
Rails 5 peut utiliser la clause or
avec where
.
User.where(name: "abc").or(User.where(name: "abcd"))