Commit 51e3a6930d27d7f06c32244b197895dff4151b0e

Authored by Dhruv Kapadia
1 parent d0820545

Handle updating counter cache values when invalid flag is used

app/models/vote.rb
... ... @@ -23,6 +23,7 @@ class Vote < ActiveRecord::Base
23 23 serialize :tracking
24 24  
25 25 after_create :update_winner_choice, :update_loser_choice
  26 + after_save :update_counter_caches_based_on_flags
26 27  
27 28 def update_winner_choice
28 29 choice.reload # make sure we're using updated counter values
... ... @@ -33,4 +34,22 @@ class Vote < ActiveRecord::Base
33 34 loser_choice.reload
34 35 loser_choice.compute_score!
35 36 end
  37 +
  38 + # this is necessary to handle counter cache, at least until the following patch is accepted:
  39 + # https://rails.lighthouseapp.com/projects/8994/tickets/3521-patch-add-conditional-counter-cache
  40 + def update_counter_caches_based_on_flags
  41 + if valid_record_changed?
  42 + if valid_record
  43 + Question.increment_counter(:votes_count, self.question_id)
  44 + Prompt.increment_counter(:votes_count, self.prompt_id)
  45 + Choice.increment_counter(:wins, self.choice_id)
  46 + Choice.increment_counter(:losses, self.loser_choice_id)
  47 + else
  48 + Question.decrement_counter(:votes_count, self.question_id)
  49 + Prompt.decrement_counter(:votes_count, self.prompt_id)
  50 + Choice.decrement_counter(:wins, self.choice_id)
  51 + Choice.decrement_counter(:losses, self.loser_choice_id)
  52 + end
  53 + end
  54 + end
36 55 end
... ...
spec/models/visitor_spec.rb
... ... @@ -126,6 +126,7 @@ describe Visitor do
126 126  
127 127 valid_skip = @visitor.skip!(allparams)
128 128 @visitor.skips.count.should == 1
  129 + @visitor.skips.size.should == 1
129 130 @appearance.reload.answerable.should == valid_skip
130 131  
131 132 # we need to reset because vote_for deletes keys from the params
... ... @@ -137,6 +138,7 @@ describe Visitor do
137 138 invalid_skip.validity_information.should == "Appearance #{@appearance.id} already answered"
138 139 @appearance.reload.answerable.should == valid_skip
139 140 @visitor.reload.skips.count.should == 1
  141 + @visitor.reload.skips.size.should == 1
140 142 end
141 143  
142 144 it "should mark a vote as invalid if submitted with an already answered appearance" do
... ... @@ -146,6 +148,7 @@ describe Visitor do
146 148  
147 149 valid_vote = @visitor.vote_for!(allparams)
148 150 @visitor.votes.count.should == 1
  151 + @question.reload.votes.size.should == 1
149 152 @appearance.reload.answerable.should == valid_vote
150 153  
151 154 # we need to reset because vote_for deletes keys from the params
... ... @@ -157,6 +160,7 @@ describe Visitor do
157 160 invalid_vote.validity_information.should == "Appearance #{@appearance.id} already answered"
158 161 @appearance.reload.answerable.should == valid_vote
159 162 @visitor.reload.votes.count.should == 1
  163 + @question.reload.votes.size.should == 1 #test counter cache works as well
160 164 end
161 165  
162 166 it "should accurately update score counts after vote" do
... ...
spec/models/vote_spec.rb
... ... @@ -11,6 +11,10 @@ describe Vote do
11 11 before(:each) do
12 12 @question = Factory.create(:aoi_question)
13 13 @prompt = @question.prompts.first
  14 + @required_params = {:question => @question, :prompt => @prompt,
  15 + :choice => @prompt.left_choice,
  16 + :voter=> @question.site.default_visitor,
  17 + :loser_choice => @prompt.right_choice}
14 18 end
15 19  
16 20 it "should create a new instance with factory girl" do
... ... @@ -95,16 +99,89 @@ describe Vote do
95 99 end
96 100  
97 101 it "should allow default valid_record behavior to be overriden by default" do
98   - required_params = {:question => @question, :prompt => @prompt,
99   - :choice => @prompt.left_choice,
100   - :voter=> @question.site.default_visitor,
101   - :loser_choice => @prompt.right_choice}
102   -
103   - vote = Vote.create!(required_params)
  102 + vote = Vote.create!(@required_params)
104 103 vote.valid_record.should be_true
105 104  
106   -
107   - vote = Vote.create!(required_params.merge!(:valid_record => false))
  105 + vote = Vote.create!(@required_params.merge!(:valid_record => false))
108 106 vote.valid_record.should be_false
109 107 end
  108 +
  109 + it "should update counter cache on question when vote is flagged as invalid" do
  110 + vote = Factory.create(:vote, :question => @question)
  111 + @question.reload
  112 + @question.votes.size.should == 1
  113 + @question.votes_count.should == 1
  114 +
  115 + vote.valid_record = false;
  116 + vote.save
  117 +
  118 + @question.reload
  119 + @question.votes.size.should == 0
  120 + @question.votes_count.should == 0
  121 +
  122 + the_vote = Factory.create(:vote, :question => @question)
  123 + the_vote.validity_information = "blah blah blah"
  124 + the_vote.save
  125 +
  126 + @question.reload.votes.size.should == 1
  127 +
  128 + end
  129 + it "should update counter cache on question when vote is created with invalid flag" do
  130 + vote = Vote.create!(@required_params)
  131 + @question.reload.votes.size.should == 1
  132 +
  133 + vote = Vote.create!(@required_params.merge!(:valid_record => false))
  134 + @question.reload.votes.size.should == 1
  135 + end
  136 +
  137 + it "should update counter cache on choice after changing valid status" do
  138 + vote = Factory.create(:vote, :question => @question, :prompt => @prompt,
  139 + :choice => @prompt.left_choice)
  140 +
  141 + @prompt.left_choice.reload
  142 + @prompt.left_choice.votes.size.should == 1
  143 + @prompt.left_choice.wins.should == 1
  144 +
  145 + vote.valid_record = false
  146 + vote.save
  147 + @prompt.left_choice.reload
  148 + @prompt.left_choice.votes.size.should == 0
  149 + @prompt.left_choice.wins.should == 0
  150 +
  151 + end
  152 + it "should update counter cache on prompt after changing valid status" do
  153 + vote = Factory.create(:vote, :question => @question, :prompt => @prompt)
  154 +
  155 + @prompt.reload
  156 + @prompt.votes.size.should == 1
  157 + @prompt.votes_count.should == 1
  158 +
  159 + vote.valid_record = false
  160 + vote.save
  161 + @prompt.reload
  162 + @prompt.votes.size.should == 0
  163 + @prompt.votes_count.should == 0
  164 +
  165 + end
  166 +
  167 + it "should update counter cache on loser_choice after invalid is changed" do
  168 + vote = Factory.create(:vote, :question => @question, :prompt => @prompt,
  169 + :choice => @prompt.left_choice,
  170 + :loser_choice => @prompt.right_choice)
  171 +
  172 + @prompt.right_choice.reload
  173 + @prompt.right_choice.votes.size.should == 0
  174 + @prompt.right_choice.wins.should == 0
  175 + @prompt.right_choice.losses.should == 1
  176 +
  177 + vote.valid_record = false
  178 + vote.save
  179 +
  180 + @prompt.right_choice.reload
  181 + @prompt.right_choice.votes.size.should == 0
  182 + @prompt.right_choice.wins.should == 0
  183 + @prompt.right_choice.losses.should == 0
  184 +
  185 + end
  186 +
110 187 end
... ...