From 8f23a174c70223831055e1498b50c3ba260858fe Mon Sep 17 00:00:00 2001 From: Date: Wed, 29 Aug 2007 18:06:16 -0400 Subject: [PATCH] Created a partial to DRY the aja voting method. Modified the voter class to have both a FullVoter and QuickVoter `types`. Also changed the index and review methods so that they are more error resistant in the face of ajax voting. Application.rb now includes the sort_candidates method from quickvote_controller so all election types can use it. Also updated the election results pages so that they don't throw errors any more. (Show and Hide details) --- app/controllers/application.rb | 11 +++++++++++ app/controllers/election_controller.rb | 19 +++++-------------- app/controllers/quickvote_controller.rb | 10 ---------- app/controllers/voter_controller.rb | 17 ++++++----------- app/models/full_voter.rb | 6 +++++- app/models/raw_voter_list.rb | 2 +- app/models/token.rb | 6 +++--- app/models/vote.rb | 15 +++++++-------- app/models/voter.rb | 7 ++++++- app/views/election/_candidate_line.rhtml | 8 ++++---- app/views/election/_candidate_list.rhtml | 4 ++-- app/views/election/_overview_form.rhtml | 2 +- app/views/site/index.rhtml | 1 - app/views/voter/_sortable_vote.rhtml | 15 +++++++++++++++ app/views/voter/_vote.rhtml | 9 ++------- app/views/voter/full_vote.rhtml | 5 ++++- app/views/voter/review.rhtml | 5 +++-- app/views/voter_notify/votestart.rhtml | 2 +- db/create.sql | 1 + db/schema.rb | 5 +++-- 20 files changed, 80 insertions(+), 70 deletions(-) create mode 100644 app/views/voter/_sortable_vote.rhtml diff --git a/app/controllers/application.rb b/app/controllers/application.rb index aeb2204..5b55d0b 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base include AuthenticatedSystem helper :user require_dependency "user" + before_filter :add_stylesheets def initialize @@ -18,4 +19,14 @@ class ApplicationController < ActionController::Base end end + #both election_controller and quickvote_controller need this method + def sort_candidates + @vote = Vote.find(params[:id]) + + @vote.rankings.each do |ranking| + ranking.rank = params['rankings-list'].index(ranking.candidate.id.to_s) + 1 + ranking.save + end + render :nothing => true + end end diff --git a/app/controllers/election_controller.rb b/app/controllers/election_controller.rb index 570f1fc..fa1313c 100644 --- a/app/controllers/election_controller.rb +++ b/app/controllers/election_controller.rb @@ -60,8 +60,8 @@ class ElectionController < ApplicationController def start_election @election = Election.find(params[:id]) - @election.voters.each do |voter| + voter.vote = Vote.new email = VoterNotify.deliver_votestart(voter) #render(:text => "
" + email.encoded + "
") end @@ -69,15 +69,6 @@ class ElectionController < ApplicationController @election.activate! redirect_to :action => 'show', :id => @election.id end - - def change_notices - election = Election.find(params[:id]) - if election.notices == 0 - election.notices = 1 - else - election.notices = 0 - end - end # methods fod display, adding, deleting, and manipulating candidate # information for elections @@ -108,13 +99,13 @@ class ElectionController < ApplicationController def lessinfo_candidate @show_details = false - @candidate = Candidate.find( params[:id] ) + @current_candidate = Candidate.find( params[:id] ) render :partial => 'candidate_line' end def moreinfo_candidate @show_details = true - @candidate = Candidate.find( params[:id] ) + @current_candidate = Candidate.find( params[:id] ) render :partial => 'candidate_line' end @@ -192,7 +183,7 @@ class ElectionController < ApplicationController @election.voters. each do |voter| if voter.vote and voter.vote.confirmed? @voter_list << voter.email - @vote_list << voter.vote + @vote_list << voter.vote end end @@ -209,7 +200,7 @@ class ElectionController < ApplicationController unless incoming_voters.entries.empty? incoming_voters.each do |new_voter| - + if incoming_voters.email == 0 new_voter.contacted = 1 elsif incoming_voters.email == 1 diff --git a/app/controllers/quickvote_controller.rb b/app/controllers/quickvote_controller.rb index 1e5b142..a5c8065 100644 --- a/app/controllers/quickvote_controller.rb +++ b/app/controllers/quickvote_controller.rb @@ -160,16 +160,6 @@ class QuickvoteController < ApplicationController voter.destroy redirect_to quickvote_url( :ident => params[:ident] ) end - - def sort_candidates - @vote = Vote.find(params[:id]) - - @vote.rankings.each do |ranking| - ranking.rank = params['rankings-list'].index(ranking.candidate.id.to_s) + 1 - ranking.save - end - render :nothing => true - end def mapvoters @map = GMap.new("map_div_id") diff --git a/app/controllers/voter_controller.rb b/app/controllers/voter_controller.rb index f4e0e7e..6693b0f 100644 --- a/app/controllers/voter_controller.rb +++ b/app/controllers/voter_controller.rb @@ -8,22 +8,17 @@ class VoterController < ApplicationController password = params[:id] password = params[:vote][:password] if params[:vote] if @voter = FullVoter.find(:all, :conditions => [ "password = ?", password ] )[0] - render :action => 'fullvote' + @voter.vote = Vote.new if @voter.vote.nil? + @voter.vote.set_defaults! if @voter.vote.rankings.empty? + render :action => 'full_vote' end end def review if authenticate - # remove any existing votes and reload - if @voter.vote - @voter.vote.destroy - @voter.reload - end - - @vote = Vote.new - @voter.vote = @vote - @vote.votestring = params[:vote][:votestring] - @vote.save + @voter.vote.time = Time.now + @voter.vote.save + @voter.reload else redirect_to :action => 'index' end diff --git a/app/models/full_voter.rb b/app/models/full_voter.rb index b82667c..9e5709e 100644 --- a/app/models/full_voter.rb +++ b/app/models/full_voter.rb @@ -1,7 +1,11 @@ class FullVoter < Voter - before_create :create_password validates_presence_of :email, :password + def initialize(params={}) + super + create_password + end + def create_password token_generator = UniqueTokenGenerator.new( 16 ) until password and not password.empty? \ diff --git a/app/models/raw_voter_list.rb b/app/models/raw_voter_list.rb index 71b200f..508902c 100644 --- a/app/models/raw_voter_list.rb +++ b/app/models/raw_voter_list.rb @@ -16,7 +16,7 @@ class RawVoterList def each @input_addresses.split("\n").each do |address| - yield Voter.new( { :email => address } ) + yield FullVoter.new( { :email => address } ) end end end diff --git a/app/models/token.rb b/app/models/token.rb index 4ed9598..e9f4fd6 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -1,6 +1,6 @@ -class Token < ActiveRecord::Base - belongs_to :vote - +class Token < ActiveRecord::Base + belongs_to :vote + def initialize super diff --git a/app/models/vote.rb b/app/models/vote.rb index 62944e3..dcadcac 100644 --- a/app/models/vote.rb +++ b/app/models/vote.rb @@ -7,9 +7,7 @@ class Vote < ActiveRecord::Base # callbacks after_update :save_rankings before_destroy :destroy_rankings - - def to_s votes.join("") end @@ -76,7 +74,7 @@ class Vote < ActiveRecord::Base def votestring=(string="") candidate_ids = voter.election.candidates.sort.collect \ { |candidate| candidate.id.to_i } - + rel_votes = string.split("").collect { |vote| vote.to_i } # covert relative orders to absolute candidate ids @@ -95,11 +93,12 @@ class Vote < ActiveRecord::Base self.votes.collect {|v| cand_relnums[v]}.join("") end - # the following subroutine is used for quickvotes. it creates a vote - # with the candidates listed in order of preference based on - # alphabetical order. it is meant to be manipulated and then confirmed - def set_defaults! - self.votes = voter.election.candidates.sort.collect {|c| c.id } + # the following subroutine is used for quickvotes, but need for elections now + # too. It creates a vote with the candidates listed in order of preference + # based on alphabetical order. It is meant to be manipulated and then confirmed + def set_defaults! + self.votes = voter.election.candidates.sort.collect {|c| c.id } self.save end + end diff --git a/app/models/voter.rb b/app/models/voter.rb index f229909..012c795 100644 --- a/app/models/voter.rb +++ b/app/models/voter.rb @@ -1,7 +1,12 @@ class Voter < ActiveRecord::Base belongs_to :election has_one :vote - + + def reset_vote + self.vote.destroy + self.reload + end + def destroy vote.destroy if vote super diff --git a/app/views/election/_candidate_line.rhtml b/app/views/election/_candidate_line.rhtml index 870a2de..e5bcf07 100644 --- a/app/views/election/_candidate_line.rhtml +++ b/app/views/election/_candidate_line.rhtml @@ -1,19 +1,19 @@ -<% -%>
  • <%=h @current_candidate.name -%> <% if @show_details %> (<%= link_to_remote "Hide Details", :update => "cand#{@current_candidate.id}", - :url => { :action => :lessinfo_candidate, :id => @current_candidate.id } %>) + :url => { :action => :lessinfo_candidate, + :id => @current_candidate.id } %>)
    - <%= h(@current_candidate.description) %> + <%=h (@current_candidate.description) %>
    <% else %> (<%= link_to_remote "Show Details", :update => "cand#{@current_candidate.id}", :url => { :action => :moreinfo_candidate, - :id => @current_candidate.id } %>) + :id => @current_candidate.id } %>) <% end %>
  • diff --git a/app/views/election/_candidate_list.rhtml b/app/views/election/_candidate_list.rhtml index 74d4c3c..881c0a5 100644 --- a/app/views/election/_candidate_list.rhtml +++ b/app/views/election/_candidate_list.rhtml @@ -1,7 +1,7 @@ <% %> diff --git a/app/views/election/_overview_form.rhtml b/app/views/election/_overview_form.rhtml index d5d7b6c..7d575e9 100644 --- a/app/views/election/_overview_form.rhtml +++ b/app/views/election/_overview_form.rhtml @@ -1,7 +1,7 @@ <%= error_messages_for 'election' %> -


    +


    <%= text_field 'election', 'name', :size => 60 %>


    diff --git a/app/views/site/index.rhtml b/app/views/site/index.rhtml index c828403..efbb374 100644 --- a/app/views/site/index.rhtml +++ b/app/views/site/index.rhtml @@ -21,7 +21,6 @@

    Control Room

    - <% if session[:user] %> <%= render :partial => 'user_summary' %> <% else %> diff --git a/app/views/voter/_sortable_vote.rhtml b/app/views/voter/_sortable_vote.rhtml new file mode 100644 index 0000000..4154482 --- /dev/null +++ b/app/views/voter/_sortable_vote.rhtml @@ -0,0 +1,15 @@ +<% %> +
    +
      + <% for ranking in @voter.vote.rankings %> +
    1. + <%=h ranking.candidate.name.capitalize %>
    2. + <% end %> +
    +
    + +
    + +<%= sortable_element 'rankings-list', + :url => { :action => "sort_candidates", :id => @voter.vote.id }, + :complete => visual_effect(:highlight, 'rankings-list') %> \ No newline at end of file diff --git a/app/views/voter/_vote.rhtml b/app/views/voter/_vote.rhtml index b95fc96..914077c 100644 --- a/app/views/voter/_vote.rhtml +++ b/app/views/voter/_vote.rhtml @@ -11,13 +11,8 @@ least preferred. Please list all choices in every vote. (For example, 123 or 321 or 213, etc.)

    -<% if @voter.election.quickvote? %> - <% form_tag(quickaction_url( :ident => @voter.election.name, :action => 'confirm')) do %> -<% else %> - <%= form_tag :action => 'review', :id => @voter.password %> -<% end %> - +<%= form_tag :action => 'review', :id => @voter.password %> <%= text_field :vote, :votestring -%> <%= submit_tag "Vote!" %> -<% end %> + diff --git a/app/views/voter/full_vote.rhtml b/app/views/voter/full_vote.rhtml index 2f1fc22..e6ccb26 100644 --- a/app/views/voter/full_vote.rhtml +++ b/app/views/voter/full_vote.rhtml @@ -5,6 +5,9 @@

    Description:

    <%= @voter.election.description %>
    -<%= render_partial 'vote' %> +<%= render :partial => 'vote' %> +<%= render :partial => 'sortable_vote' %> + +<%= button_to "Submit Vote", :action => 'review', :id => @voter.password %> diff --git a/app/views/voter/review.rhtml b/app/views/voter/review.rhtml index d1eb9dc..b8b9089 100644 --- a/app/views/voter/review.rhtml +++ b/app/views/voter/review.rhtml @@ -1,13 +1,14 @@ <% %> +<% %>

    Please review your vote carefully before confirming it.

    You have ranked the candidates in the following order (from most preferred to least preferred:

      - <% for rank in @vote.rankings.sort %> -
    1. <%= rank.candidate.name %>
    2. + <% for rank in @voter.vote.rankings.sort %> +
    3. <%=h rank.candidate.name.capitalize %>
    4. <% end %>
    diff --git a/app/views/voter_notify/votestart.rhtml b/app/views/voter_notify/votestart.rhtml index b31f1ba..216ddeb 100644 --- a/app/views/voter_notify/votestart.rhtml +++ b/app/views/voter_notify/votestart.rhtml @@ -11,7 +11,7 @@ need to use the following token to log in to selectricity.media.mit.edu: <%= @voter.password %> Alternatively, you can just click this URL: - <%= url_for :controller => 'election', :action => 'show', :id => @voter.election.id %> + http://selectricity.media.mit.edu<%= url_for :controller => 'election', :action => 'show', :id => @voter.election %> If you have any questions or if you feel you have received this message in error, you should contact: diff --git a/db/create.sql b/db/create.sql index 2033ed1..7d5f405 100644 --- a/db/create.sql +++ b/db/create.sql @@ -58,6 +58,7 @@ create table voters ( election_id int NOT NULL, session_id varchar(32) DEFAULT NULL, ipaddress varchar(32) DEFAULT NULL, + `type` varchar(100) NOT NULL, constraint fk_election_voter foreign key (election_id) references election(id), primary key (id) ); diff --git a/db/schema.rb b/db/schema.rb index 590425d..6c038de 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -74,10 +74,11 @@ ActiveRecord::Schema.define() do create_table "voters", :force => true do |t| t.column "email", :string, :limit => 100 t.column "password", :string, :limit => 100 - t.column "contacted", :integer, :limit => 4, :default => 0, :null => false - t.column "election_id", :integer, :null => false + t.column "contacted", :integer, :limit => 4, :default => 0, :null => false + t.column "election_id", :integer, :null => false t.column "session_id", :string, :limit => 32 t.column "ipaddress", :string, :limit => 32 + t.column "type", :string, :limit => 100, :default => "", :null => false end add_index "voters", ["election_id"], :name => "fk_election_voter" -- 2.30.2