Lad os starte med at rette lidt op på relationerne:
class Question < ActiveRecord::Base
has_many :options
has_many :answers
has_many :users, through: :answers
end
Der er ikke noget teknisk galt med has_many :answers, :through => :options
men da der er en direkte relation gennem answers.question_id
vi behøver ikke gå gennem options
tabel for relationen.
Visning af optælling
Hvis vi bare gjorde:
<td class="optionCell"><%= option.answers.count %></td>
Dette ville skabe en ubehagelig n+1
forespørgsel for at hente antallet af svar for hver mulighed. Så det, vi vil gøre, er at oprette en tællercache
som gemmer en opgørelse på indstillingstabellen.
Lad os starte med at oprette en migrering for at tilføje kolonnen:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate
Derefter beder vi ActiveRecord om at opdatere optællingen, når vi opretter tilknyttede poster, dette ser lidt mærkeligt ud, da counter_cache: true
erklæringen er på belongs_to
side, mens kolonnen er på den anden, men det er bare sådan AR fungerer.
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
Der er en lille hage her. Da vi muligvis allerede har optegnelser, skal vi sikre os, at de har korrekte tællere. Du kan gøre dette fra konsollen, men i det lange løb er det en god idé at oprette en rake-opgave .
Option.find_each { |option| Option.reset_counters(option.id, :answers) }
Dette kan tage lidt tid, da det skal trække hver Option og opdatere antallet.
Nu kan vi vise opgørelsen sådan:
<% 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
er smart nok til at bruge vores tæller-cache-kolonne, men vil falde tilbage til at forespørge om optællingen, hvilket er en god ting for tests.