Rails 5: requête ActiveRecord OR

Comment faites-vous or interrogez-vous dans Rails 5 ActiveRecord? En outre, est-il possible d’enchaîner or avec where dans les requêtes ActiveRecord?

    La possibilité de chaîner or clause avec la clause where dans la requête ActiveRecord sera disponible dans Rails 5 . Voir la discussion associée et la demande d’extraction .

    Ainsi, vous pourrez faire les choses suivantes dans Rails 5 :

    Pour obtenir un post avec l’ 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) 

    Nous n’avons pas besoin d’attendre que les rails 5 utilisent cette requête OR . Nous pouvons également l’utiliser avec des rails 4.2.3 . Il y a un backport ici .

    Merci à Eric-Guo pour gem où-ou , Maintenant, nous pouvons append cette fonctionnalité OR dans >= rails 4.2.3 utilisant également cette gem.

    Je devais faire un (A && B) || (C && D) || (E && F) (A && B) || (C && D) || (E && F)

    Mais dans l’état actuel de Rails 5.1.4 , cela devient trop compliqué à accomplir avec l’arel ou la chaîne. Mais je voulais quand même utiliser Rails pour générer autant de requêtes que possible.

    J’ai donc fait un petit piratage:

    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 

    Suivant dans mon domaine, 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 ')) } 

    Qui produira le résultat attendu de la requête: SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)) .

    Et maintenant, je peux facilement combiner ceci avec d'autres champs d'application, etc.

    La beauté étant que mon sql_where prend en charge les arguments where-clause sql_where(name: 'John', role: 'admin') : sql_where(name: 'John', role: 'admin') générera (name = 'John' AND role = 'admin') .

    (Juste un ajout à la réponse de KM Rakibul Islam.)

    En utilisant des étendues, le code peut devenir plus joli (en fonction des yeux):

     scope a, -> { where(a) } scope b, -> { where(b) } scope a_or_b, -> { a.or(b) }