関係を少し修正することから始めましょう:
class Question < ActiveRecord::Base
has_many :options
has_many :answers
has_many :users, through: :answers
end
has_many :answers, :through => :options
には技術的に問題はありません。 ただし、answers.question_id
には直接的な関係があるためです。 options
を実行する必要はありません 関係の表。
カウントの表示
単純に行った場合:
<td class="optionCell"><%= option.answers.count %></td>
これにより、厄介なn+1
が作成されます 各オプションの回答の数を取得するためのクエリ。したがって、私たちがやりたいのは、カウンターキャッシュを作成する
ことです。 オプションテーブルに集計を保存します。
列を追加するための移行を作成することから始めましょう:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate
次に、関連付けられたレコードを作成するときに集計を更新するようにActiveRecordに指示します。これは、counter_cache: true
であるため、少し奇妙に見えます。 宣言はbelongs_to
にあります コラムが反対側にある間、それはARがどのように機能するかです。
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
ここに小さな障害があります。すでにレコードがある可能性があるため、正しいカウンターがあることを確認する必要があります。これはコンソールから実行できますが、長期的にはを実行することをお勧めします。レーキタスクを作成する 。
Option.find_each { |option| Option.reset_counters(option.id, :answers) }
各オプションを取得してカウントを更新する必要があるため、これには少し時間がかかる場合があります。
これで、次のように集計を表示できます:
<% 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
カウンターキャッシュ列を使用するのに十分賢いですが、カウントのクエリにフォールバックします。これはテストに適しています。