avoinministerio/avoinministerio — pull request #153 by jyrkive (2012-06-07 11:05:03+00:00)
Title: Citizens shouldn't be able to vote the same idea multiple times

Aleksi requested me to fix a bug that allows vote proportion to exceed 100 % (i.e. according to the database, there were ideas where more than 100 % of votes supported the idea). When analyzing the source code, I noticed that it's just a symptom of a larger problem.

Citizens are allowed to vote for/against the same idea unlimited number of times. His/her old vote is removed from the database and the total count of votes doesn't change. However, the count of the option the citizen previously chose isn't decremented. That is, if an idea has 5 votes for it and 5 votes against it, and a citizen who previously voted against the idea votes for it, after his/her new vote the idea has 6 votes for and 5 votes against. Even worse, if the citizen chooses the same option as previously, the count is incremented (i.e. if the same citizen votes again for the idea, the idea has 7 votes for and 5 votes against). However, the total vote count stays 10. This allows either count to exceed the total vote count. (Current code appears to have a hack that hides most of these problems.)

I have fixed the underlying problem by decrementing the count of the option the citizen previously chose. I rewrote Citizen::update_vote_counts, because the method needs to know which option, if any, the citizen has previously chosen.

Finally, you can fix existing vote counts by running this on production console:

```
Idea.all.each do |idea|
idea.vote_for_count = idea.votes.where("option = 1").count
idea.vote_against_count = idea.votes.where("option = 0").count
idea.vote_count = idea.vote_for_count + idea.vote_against_count
if (idea.vote_count > 0)
prop = idea.vote_for_count.to_f / idea.vote_count
idea.vote_proportion = prop
idea.vote_proportion_away_mid = (0.5 - prop).abs
end
idea.save
end
```