Mysql
 sql >> Base de données >  >> RDS >> Mysql

Application de style d'enquête Rails - Afficher toutes les réponses en option

Commençons par corriger un peu les relations :

class Question < ActiveRecord::Base
  has_many :options
  has_many :answers
  has_many :users, through: :answers
end

Il n'y a rien de mal techniquement avec has_many :answers, :through => :options mais comme il existe une relation directe via answers.question_id nous n'avons pas besoin de passer par les options table pour la relation.

Affichage du décompte

Si nous faisions simplement :

<td class="optionCell"><%= option.answers.count %></td>

Cela créerait un méchant n+1 query pour récupérer le nombre de réponses pour chaque option. Donc, ce que nous voulons faire, c'est créer un contre-cache qui stocke un décompte sur la table des options.

Commençons par créer une migration pour ajouter la colonne :

rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

Ensuite, nous disons à ActiveRecord de mettre à jour le décompte lorsque nous créons des enregistrements associés, cela semble un peu étrange puisque le counter_cache: true déclaration est sur le belongs_to côté tandis que la colonne est de l'autre mais c'est comme ça que AR fonctionne.

class Option < ActiveRecord::Base
  belongs_to :question
  has_many :answers
end

class Answer < ActiveRecord::Base
  belongs_to :user
  belongs_to :question
  belongs_to :option, counter_cache: true
end

Il y a un petit hic ici. Comme nous avons peut-être déjà des enregistrements, nous devons nous assurer qu'ils ont des compteurs corrects. Vous pouvez le faire à partir de la console, mais à long terme, c'est une bonne idée de créer une tâche de rake .

Option.find_each { |option| Option.reset_counters(option.id, :answers) }

Cela peut prendre un peu de temps car il doit extraire chaque option et mettre à jour le nombre.

Nous pouvons maintenant afficher le décompte comme suit :

<% question.options.each do |option| %>
  <tr class="backgroundColor1">
    <td class="optionCell"><%= option.option_text %></td>
    <td class="optionCell"><%= option.answers.size %></td>
  </tr>
<% end %>

.size est assez intelligent pour utiliser notre colonne de cache de compteur, mais reviendra à interroger le nombre, ce qui est une bonne chose pour les tests.