Commit 9c36c839854314d4d3510389fe72edec70fec82a
1 parent
f9071a75
Exists in
master
and in
1 other branch
Bug in cached score computation, test case
Showing
4 changed files
with
64 additions
and
1 deletions
Show diff stats
app/models/visitor.rb
| ... | ... | @@ -25,6 +25,10 @@ class Visitor < ActiveRecord::Base |
| 25 | 25 | |
| 26 | 26 | loser_choice = other_choices.first |
| 27 | 27 | votes.create!(:question_id => prompt.question_id, :prompt_id => prompt.id, :voter_id=> self.id, :choice_id => choice.id, :loser_choice_id => loser_choice.id) |
| 28 | + # Votes count is a cached value, creating the vote above will increment it in the db, but to get the proper score, we need to increment it in the current object | |
| 29 | + # The updated votes_count object is not saved to the db, so we don't need to worry about double counting | |
| 30 | + # Alternatively, we could just do choice.reload, but that results in another db read | |
| 31 | + choice.votes_count +=1 | |
| 28 | 32 | choice.compute_score! #update score after win |
| 29 | 33 | end |
| 30 | 34 | ... | ... |
config/environments/test.rb
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +class UpdateIncorrectScores < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + | |
| 4 | + # some scores were computed incorrectly as a result of a bug | |
| 5 | + # This only affected the cached value of the score, so we only need to recalculate the correct score | |
| 6 | + # for those choices voted on in the last few days | |
| 7 | + startDate = 2.days.ago | |
| 8 | + votes = Vote.find(:all, :conditions => ['created_at > ?', startDate]) | |
| 9 | + toupdate = votes.inject(Set.new){|updatethese, v| updatethese << v.choice_id} | |
| 10 | + choices = Choice.find(:all, :conditions => {'id' => toupdate.to_a}) | |
| 11 | + | |
| 12 | + choices.each do |c| | |
| 13 | + c.compute_score! | |
| 14 | + end | |
| 15 | + | |
| 16 | + end | |
| 17 | + | |
| 18 | + def self.down | |
| 19 | + end | |
| 20 | +end | ... | ... |
spec/models/visitor_spec.rb
| ... | ... | @@ -6,6 +6,7 @@ describe Visitor do |
| 6 | 6 | it {should have_many :questions} |
| 7 | 7 | it {should have_many :votes} |
| 8 | 8 | it {should have_many :skips} |
| 9 | + it {should have_many :clicks} | |
| 9 | 10 | |
| 10 | 11 | before(:each) do |
| 11 | 12 | @aoi_clone = Factory.create(:user, :email => "pius@alum.mit.edu", :password => "password", :password_confirmation => "password", :id => 8) |
| ... | ... | @@ -29,6 +30,9 @@ describe Visitor do |
| 29 | 30 | |
| 30 | 31 | it "should be able to determine ownership of a question" do |
| 31 | 32 | @v.owns?(Question.new).should be_false |
| 33 | + | |
| 34 | + ownedquestion = Factory.create(:question, :site => @aoi_clone, :creator=> @johndoe) | |
| 35 | + @johndoe.owns?(ownedquestion).should be_true | |
| 32 | 36 | end |
| 33 | 37 | |
| 34 | 38 | it "should be able to vote for a prompt" do |
| ... | ... | @@ -37,10 +41,41 @@ describe Visitor do |
| 37 | 41 | v = @v.vote_for! @prompt, 0 |
| 38 | 42 | end |
| 39 | 43 | |
| 40 | - it "should be able to vote for a prompt" do | |
| 44 | + it "should be able to skip a prompt" do | |
| 41 | 45 | #@prompt = @question.prompts.first |
| 42 | 46 | @prompt.should_not be_nil |
| 43 | 47 | v = @v.skip! @prompt |
| 44 | 48 | end |
| 49 | + | |
| 50 | + it "should accurately update score counts after vote" do | |
| 51 | + prev_winner_score = @lc.score | |
| 52 | + prev_loser_score = @rc.score | |
| 53 | + | |
| 54 | + vote = @v.vote_for! @prompt, 0 | |
| 55 | + | |
| 56 | + @lc.reload | |
| 57 | + @rc.reload | |
| 58 | + | |
| 59 | + @lc.score.should > prev_winner_score | |
| 60 | + @rc.score.should < prev_loser_score | |
| 61 | + end | |
| 62 | + | |
| 63 | + it "should accurately update win and loss totals after vote" do | |
| 64 | + prev_winner_wins = @lc.wins | |
| 65 | + prev_winner_losses = @lc.losses | |
| 66 | + prev_loser_losses = @rc.losses | |
| 67 | + prev_loser_wins = @rc.wins | |
| 68 | + | |
| 69 | + vote = @v.vote_for! @prompt, 0 | |
| 70 | + | |
| 71 | + @lc.reload | |
| 72 | + @rc.reload | |
| 73 | + | |
| 74 | + @lc.wins.should == prev_winner_wins + 1 | |
| 75 | + @lc.losses.should == prev_winner_losses | |
| 76 | + @rc.losses.should == prev_loser_losses + 1 | |
| 77 | + @rc.wins.should == prev_winner_wins | |
| 78 | + end | |
| 79 | + | |
| 45 | 80 | |
| 46 | 81 | end | ... | ... |