Association d’interrogation active d’enregistrements Rails avec ‘existe’

Je travaille sur une application qui permet aux membres de répondre à un sondage (le membre a une relation un à plusieurs avec la réponse). La réponse contient le member_id, question_id et leur réponse.

L’enquête est soumise à tout ou rien. Par conséquent, s’il existe des enregistrements dans le tableau des réponses pour ce membre, ils ont rempli le questionnaire.

Ma question est la suivante: comment réécrire la requête ci-dessous pour qu’elle fonctionne réellement? En SQL, ce serait un candidat de choix pour le mot clé EXISTS.

def surveys_completed members.where(responses: !nil ).count end 

Vous pouvez utiliser includes et ensuite tester si la ou les réponses associées existent comme ceci:

 def surveys_completed members.includes(:responses).where('responses.id IS NOT NULL') end 

Voici une alternative, avec des joins :

 def surveys_completed members.joins(:responses) end 

La solution utilisant Rails 4 :

 def surveys_completed members.includes(:responses).where.not(responses: { id: nil }) end 

Questions similaires:

  • Comment interroger un modèle basé sur l’atsortingbut d’un autre modèle qui appartient au premier modèle?
  • association nommée introuvable peut-être problème mal orthographié dans l’association rails
  • Rails 3, has_one / has_many avec condition lambda
  • Rails 4 scope pour trouver des parents sans enfants
  • Joindre plusieurs tables avec des enregistrements actifs

Vous pouvez utiliser le mot-clé SQL EXISTS de manière élégante à l’aide de Rails-ish en utilisant le gem de Where Exists :

 members.where_exists(:responses).count 

Bien entendu, vous pouvez également utiliser du SQL brut:

 members.where("EXISTS" \ "(SELECT 1 FROM responses WHERE responses.member_id = members.id)"). count 

Vous pouvez également utiliser une sous-requête:

 members.where(id: Response.select(:member_id)) 

Par rapport à quelque chose avec des includes il ne chargera pas les modèles associés (ce qui est un avantage de performance si vous n’en avez pas besoin).