merged in from code from the other master
[selectricity-live] / app / models / vote.rb
1 # Selectricity: Voting Machinery for the Masses
2 # Copyright (C) 2007, 2008 Benjamin Mako Hill <mako@atdot.cc>
3 # Copyright (C) 2007 Massachusetts Institute of Technology
4 #
5 # This program is free software. Please see the COPYING file for
6 # details.
7
8 class Vote < ActiveRecord::Base
9   # relationships to other classes
10   belongs_to :voter
11   has_many :rankings
12   has_one :token
13   
14   # callbacks
15   after_update :save_rankings
16   before_destroy :destroy_rankings
17   
18   def to_s
19     votes.join("")
20   end
21
22   def each
23     self.votes.each {|vote| yield vote}
24   end
25
26   def votes
27     unless @votes
28       if rankings.empty?
29         @votes = Array.new
30       else
31         @votes = self.rankings.sort.collect { |ranking| ranking.candidate.id }
32       end
33     end
34
35     @votes
36   end
37
38   def votes=(array)
39     @votes = array
40   end
41
42   def save_rankings
43     self.votes # i need to initalize this before destroying rankings
44                # or else the ranks themselves show up as nil
45
46     destroy_rankings
47     self.votes.each_with_index do |candidate_id, index| 
48       ranking = Ranking.new
49       ranking.rank = index
50       ranking.candidate =  Candidate.find(candidate_id)
51       self.rankings << ranking
52     end
53   end
54   
55   def destroy
56     self.destroy_rankings
57     super
58   end
59
60   def destroy_rankings 
61     rankings.each { |ranking| ranking.destroy }
62   end
63
64   def confirm!
65     self.confirmed = 1
66     self.time = Time.now
67     self.save
68     
69     unless self.voter.election.quickvote?
70       token.destroy and token.reload if token
71       self.token = Token.new
72       self.save
73     end
74   end
75
76   def confirm?
77     confirmed == 1
78   end
79   
80   def votestring
81     # create a mapping of candidates ids and the relative order of the
82     # candidates as they appear when sorted alphabetically
83     cand_relnums = {}
84     self.voter.election.candidates.sort.each_with_index do |c, i|
85       cand_relnums[c.id] = i + 1
86     end
87
88     # assemble the votestring
89     self.votes.collect {|v| (cand_relnums[v] + 64).chr}.join("")
90   end
91
92   # the following subroutine is used for quickvotes, but need for elections now
93   # too. It creates a vote with the candidates listed in order of preference 
94   # based on alphabetical order. Meant to be manipulated and then confirmed
95   def set_defaults!  
96     self.votes = self.voter.election.candidates.sort_by { rand }.collect {|c| c.id }
97     self.save
98   end
99          
100 end

Benjamin Mako Hill || Want to submit a patch?