आइए रिश्तों को थोड़ा ठीक करके शुरू करें:
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
create पैदा करेगा प्रत्येक विकल्प के उत्तरों की संख्या प्राप्त करने के लिए क्वेरी। तो हम क्या करना चाहते हैं एक काउंटर कैश बनाएं
जो विकल्प तालिका पर एक टैली स्टोर करता है।
आइए कॉलम जोड़ने के लिए माइग्रेशन बनाकर शुरू करें:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate
फिर हम ActiveRecord को संबंधित रिकॉर्ड बनाते समय टैली को अपडेट करने के लिए कहते हैं, यह थोड़ा अजीब लगता है क्योंकि counter_cache: true
घोषणा belongs_to
पर है जबकि कॉलम दूसरी तरफ है, लेकिन एआर कैसे काम करता है।
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
हमारे काउंटर कैश कॉलम का उपयोग करने के लिए पर्याप्त स्मार्ट है, लेकिन गिनती को क्वेरी करने के लिए वापस आ जाएगा जो परीक्षणों के लिए एक अच्छी बात है।