Hãy bắt đầu bằng cách sửa chữa các mối quan hệ một chút:
class Question < ActiveRecord::Base
has_many :options
has_many :answers
has_many :users, through: :answers
end
Không có gì sai về mặt kỹ thuật với has_many :answers, :through => :options
nhưng vì có mối quan hệ trực tiếp thông qua answers.question_id
chúng ta không cần phải đi qua options
bảng cho mối quan hệ.
Hiển thị số lượng
Nếu chúng tôi chỉ đơn giản làm:
<td class="optionCell"><%= option.answers.count %></td>
Điều này sẽ tạo ra một n+1
khó chịu truy vấn để lấy số lượng câu trả lời cho mỗi tùy chọn. Vì vậy, những gì chúng tôi muốn làm là tạo bộ nhớ đệm bộ đếm
nơi lưu trữ một bản kiểm đếm trên bảng tùy chọn.
Hãy bắt đầu bằng cách tạo di chuyển để thêm cột:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate
Sau đó, chúng tôi yêu cầu ActiveRecord cập nhật kiểm đếm khi chúng tôi tạo các bản ghi được liên kết, điều này trông hơi lạ vì counter_cache: true
khai báo trên belongs_to
trong khi cột ở phía bên kia nhưng đó chỉ là cách AR hoạt động.
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
Có một chút khó khăn ở đây. Vì chúng tôi có thể đã có hồ sơ nên chúng tôi cần đảm bảo rằng chúng có bộ đếm chính xác. Bạn có thể thực hiện việc này từ bảng điều khiển nhưng về lâu dài, bạn nên tạo một nhiệm vụ cào .
Option.find_each { |option| Option.reset_counters(option.id, :answers) }
Việc này có thể mất một chút thời gian vì cần kéo từng Tùy chọn và cập nhật số lượng.
Bây giờ chúng ta có thể hiển thị bảng kiểm đếm như sau:
<% 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
đủ thông minh để sử dụng cột bộ nhớ đệm bộ đếm của chúng tôi, nhưng sẽ quay lại truy vấn số lượng, đây là một điều tốt cho các thử nghiệm.