end
end
- def destroy
- election = Election.find(params[:id]).destroy
- redirect_to :action => 'list'
+ def start_election
+ @election = Election.find(params[:id])
+
+ @election.voters.each do |voter|
+ email = VoterNotify.create_votestart(voter)
+ render(:text => "<pre>" + email.encoded + "</pre>")
+ breakpoint
+ break
+ end
+
+ #@election.activate!
end
# methods fod display, adding, deleting, and manipulating candidate
def update_candidate
@candidate = Candidate.find(params[:id])
+ @election = @candidate.election
if @candidate.update_attributes(params[:candidate])
- flash[:notice] = 'Candidate information was successfully updated.'
- redirect_to :action => 'edit_candidates', :id => @candidate.election
+ redirect_to :action => 'edit_candidates', :id => @candidate.election.id
else
- render :action => 'edit_candidates'
+ render :action => 'edit_candidate'
end
end
model :user, :election
def index
- @current_elections = session[:user].elections.sort do |a,b|
- b.enddate <=> a.enddate
+ if session[:user]
+ session[:user] = User.find(session[:user].id)
+ @current_elections = session[:user].elections.sort do |a,b|
+ b.enddate <=> a.enddate
+ end
end
-
-
end
end
class UserController < ApplicationController
layout 'vb'
+
+ def home
+ redirect_to :controller => 'site', :action => 'index'
+ end
+
end
class Candidate < ActiveRecord::Base
belongs_to :election
validates_uniqueness_of :name
+ validates_presence_of :name
def <=>(other)
self.name <=> other.name
end
super
end
-
+
+ def start_blockers
+ reasons = []
+
+ if self.candidates.length <= 1
+ reasons << "You must have at least two candidates."
+ end
+
+ if self.voters.length <= 1
+ reasons << "You must have at least two voters."
+ end
+
+ reasons
+ end
+
+ def activate!
+ self.active = 1
+ end
+
end
class User < ActiveRecord::Base
include LoginEngine::AuthenticatedUser
+
has_many :elections
def name
belongs_to :election
has_one :vote
- def initialize(args)
- super(args)
-
+ before_create :create_password
+
+ def create_password
token_generator = UniqueTokenGenerator.new( 16 )
- until password and Voter.find_all( [ "password = ?", password ]).empty?
+ until password and not password.empty? \
+ and Voter.find_all( [ "password = ?", password ]).empty?
self.password = token_generator.token
end
end
--- /dev/null
+class VoterNotify < ActionMailer::Base
+
+ def votestart(voter)
+ @subject = "[%s] Election In Progress!" % voter.election.name
+ @recipients = voter.email
+ @from = MAIL_CONFIG[:from]
+ @sent_on = Time.now
+ @body = { :voter => voter }
+ end
+
+ def reminder(voter)
+ end
+
+end
+<% %>
+
<p>New candidate name:<br />
<%= text_field :candidate, :name %></p>
<p>Candidate picture (optional and < 100x100 pixels):<br />
<%= file_field :candidate, :picture %></p>
+
+++ /dev/null
-<% %>
-
-<%= form_tag( { :action => :add_candidate, :id => @election.id },
- :multipart => true ) %>
-
-<%= render_partial 'candidate_form' %>
-
-<%= submit_tag "Add Candidate" %>
-<%= end_form_tag %>
-<%
-# basic election information template
--%>
+<% %>
+
+<% if @election.voters.length == 0 %>
+<p>There are currently no voters registered for this election.</p>
+<% else %>
<p>The following voters are currently registered for this election:</p>
<ul>
</div>
<% end %>
</ul>
-
+<% end %>
-<p>Please enter a list of new email addresses of potential voters.</p>
+<p>Please enter a list of new email addresses of voters (one email
+address per line).</p>
<%= text_area :raw_voter_list, :input_addresses %>
+<!--
<p>Email voters:
<%= select :raw_voter_list, :email, [ [ 'Never', 0 ],
[ 'Now', 1 ],
[ 'Vote Start', 2 ] ] %>
+-->
</p>
-<%= submit_tag "Add" %>
+<%= submit_tag "Add Voters" %>
<h1>Editing <%= @candidate.name %></h1>
-<%= error_messages_on :candidate %>
-
-<%= form_tag :action => 'update_candidate', :id => @candidate.id %>
- <%= render :partial => 'candidate_form' %>
- <%= submit_tag "Done!" %>
+<%= error_messages_for :candidate %>
+<%= form_tag( { :action => :update_candidate, :id => @candidate.id },
+ :multipart => true ) %>
+<%= render :partial => 'candidate_form' %>
+<%= submit_tag "Save" %>
<%= end_form_tag %>
-<h1><strong><%= @election.name %>:</strong> Edit Candidates</h1>
+<h1><strong><%= @election.name %>:</strong> Edit/Add Candidates</h1>
+
+<%= error_messages_for :candidate %>
<% unless @election.candidates.empty? %>
<p>The following are valid options or candidates in this election:</p>
<% else %>
<p>There are no candidates registered for this election.</p>
<% end %>
+
<p>Please enter new candidates below.</p>
-<%= render :partial => 'candidates_form' %>
+
+<%= form_tag( { :action => :add_candidate, :id => @election.id },
+ :multipart => true ) %>
+<%= render :partial => 'candidate_form' %>
+<%= submit_tag "Add Candidate" %>
+<%= end_form_tag %>
+
<%= button_to "Done!", :action => 'show', :id => @election %>
<% unless @election.voters.empty? %>
<%= render :partial => 'voter_list' %>
+ <%= link_to "Add or remove voters.", :action => 'edit_voters', :id => @election.id %></em></p>
<% else %>
<p><em>There are currently no voters registered for this election.
<%= link_to "Add some!", :action => 'edit_voters', :id => @election.id %></em></p>
<% end %>
+
+<h2>Start Election</h2>
+
+<% if @election.start_blockers.length > 0 %>
+ <p>Your election cannot be started for the following reasons:</p>
+ <ul>
+ <% for reason in @election.start_blockers %>
+ <li><%= reason %></li>
+ <% end %>
+ </ul>
+<% else %>
+<p>Please check eveything carefully on this page before starting this
+election. Once you begin the election, you will <em>not</em> be able to
+add or change candidates, modify the voting lists, or change the
+election end time.</p>
+
+<p>When you begin the election, the following will happen:</p>
+
+<ul>
+ <li>The election will be "frozen" so that further edits to the
+ candidate list and voting list cannot occur.</li>
+ <li>All voters will be emailed notifying them that the election has
+ begun and of their unique login token.</li>
+</ul>
+
+<%= button_to 'Start Election!', :action => 'start_election', :id => @election.id %>
+
+<% end %>
--- /dev/null
+Voter!
+
+This is an automated message sent by votingbooth.mako.cc.
+
+You have been listed as a voter in an upcoming election.
+
+The election title: <%= @voter.election.name %>
+
+To read more about the election, the candidates, and to vote, you will
+need to use the following token to log in to votingboth.mako.cc:
+ <%= @voter.password %>
+
+Alternatively, you can just click this URL:
+
+If you have any questions or if you feel you have recieved this message
+in error, you should contact:
+
+ <%= @voter.election.user.name %> <<%= @voter.election.user.email %>>
+ (The initiator of this election)
+
+Alternatively, if you feel there is a technical error, please contact:
+
+ help@votingbooth.mako.cc
+ (VotingBooth Tech Support)
+
+Thanks and happy voting!
+VotingBooth Staff
+
+
# inflect.uncountable %w( fish sheep )
# end
+MAIL_CONFIG = { :from => 'VotingBooth <info@votingbooth.mako.cc>'}
+
# Include your application configuration below
require 'uniq_token'
require 'randarray'
module LoginEngine
config :salt, "voothingboat"
+ config :email_from, MAIL_CONFIG[:from]
end
Engines.start :login
+
+# action mailer configuration
+ActionMailer::Base.delivery_method = :sendmail
+ActionMailer::Base.default_charset = "utf-8"
font-size: 12px;
font-weight: bold; }
+.fieldWithErrors {
+ display: inline;
+}
+.fieldWithErrors input, .fieldWithErrors select {
+ background-color: #ffdfdf;
+}
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+require 'voter_notify'
+
+class VoterNotifyTest < Test::Unit::TestCase
+ FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
+ CHARSET = "utf-8"
+
+ include ActionMailer::Quoting
+
+ def setup
+ ActionMailer::Base.delivery_method = :test
+ ActionMailer::Base.perform_deliveries = true
+ ActionMailer::Base.deliveries = []
+
+ @expected = TMail::Mail.new
+ @expected.set_content_type "text", "plain", { "charset" => CHARSET }
+ end
+
+ private
+ def read_fixture(action)
+ IO.readlines("#{FIXTURES_PATH}/voter_notify/#{action}")
+ end
+
+ def encode(subject)
+ quoted_printable(subject, CHARSET)
+ end
+end