mdarby-pollster 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.textile +37 -0
- data/Rakefile +23 -0
- data/generators/pollster/USAGE +0 -0
- data/generators/pollster/pollster_generator.rb +93 -0
- data/generators/pollster/templates/create_pollster_tables.rb +27 -0
- data/generators/pollster/templates/poll.rb +104 -0
- data/generators/pollster/templates/poll_vote.rb +6 -0
- data/generators/pollster/templates/polls_controller.rb +64 -0
- data/generators/pollster/templates/polls_helper.rb +9 -0
- data/generators/pollster/templates/spec/poll_spec.rb +253 -0
- data/generators/pollster/templates/spec/poll_vote_spec.rb +21 -0
- data/generators/pollster/templates/spec/polls_controller_spec.rb +342 -0
- data/generators/pollster/templates/spec/polls_helper_spec.rb +17 -0
- data/generators/pollster/templates/spec/polls_routing_spec.rb +51 -0
- data/generators/pollster/templates/views/_current_results.html.erb +21 -0
- data/generators/pollster/templates/views/_final_results.html.erb +16 -0
- data/generators/pollster/templates/views/_option_form.html.erb +7 -0
- data/generators/pollster/templates/views/_poll.html.erb +33 -0
- data/generators/pollster/templates/views/_vote.html.erb +11 -0
- data/generators/pollster/templates/views/edit.html.erb +38 -0
- data/generators/pollster/templates/views/index.html.erb +5 -0
- data/generators/pollster/templates/views/new.html.erb +38 -0
- data/init.rb +0 -0
- data/install.rb +1 -0
- data/uninstall.rb +1 -0
- metadata +78 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
h2. pollster
|
2
|
+
|
3
|
+
A Rails gem that generates an entire MVC stack for user polling on your app
|
4
|
+
|
5
|
+
h3. What it does
|
6
|
+
|
7
|
+
pollster adds a generator to your Rails app that creates the MVC stack for polling of your users. It has a pretty chart.
|
8
|
+
|
9
|
+
h3. Requirements
|
10
|
+
|
11
|
+
pollster requires the super amazing "RESTful_Authentication":http://weblog.techno-weenie.net/2006/8/1/restful-authentication-plugin plugin, along with the "googlecharts":http://github.com/mattetti/googlecharts/tree/master gem.
|
12
|
+
|
13
|
+
<pre>
|
14
|
+
./script/plugin install git://github.com/technoweenie/restful-authentication.git
|
15
|
+
sudo gem install mattetti-googlecharts
|
16
|
+
</pre>
|
17
|
+
|
18
|
+
Make sure to follow the instructions on RESTful_Authentication, and add this line to your config/environment.rb file:
|
19
|
+
<pre>config.gem "googlecharts", :lib => 'gchart', :version => ">= 1.3.6"</pre>
|
20
|
+
|
21
|
+
h3. How to Install
|
22
|
+
|
23
|
+
<pre>sudo gem install mdarby-pollster</pre>
|
24
|
+
|
25
|
+
h3. How to Use
|
26
|
+
|
27
|
+
<pre>./script/generate pollster WhateverYouWantToNameYourPollModel</pre>
|
28
|
+
|
29
|
+
h3. How to Test
|
30
|
+
|
31
|
+
Complete Rspec specs are included automatically. Well, complete aside from view specs as you'll just change the damned things anyway.
|
32
|
+
|
33
|
+
h3. About the Author
|
34
|
+
|
35
|
+
My name is Matt Darby. I'm the Web Developer and IT Manager at "Dynamix Engineering":http://dynamix-ltd.com and hold a Master's Degree in Computer Science from "Franklin University":http://franklin.edu in Columbus, OH.
|
36
|
+
|
37
|
+
Feel free to check out my "blog":http://blog.matt-darby.com or to "recommend me":http://www.workingwithrails.com/recommendation/new/person/10908-matt-darby
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the pollster plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the pollster plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Pollster'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
File without changes
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class PollsterGenerator < Rails::Generator::NamedBase
|
2
|
+
|
3
|
+
def initialize(*runtime_args)
|
4
|
+
super(*runtime_args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
record do |m|
|
9
|
+
install_routes(m)
|
10
|
+
|
11
|
+
m.directory(File.join('app/models'))
|
12
|
+
m.directory(File.join('app/controllers'))
|
13
|
+
m.directory(File.join('app/helpers'))
|
14
|
+
m.directory(File.join('app/views'))
|
15
|
+
m.directory(File.join("app/views/#{table_name}"))
|
16
|
+
m.directory(File.join('db/migrate'))
|
17
|
+
|
18
|
+
if has_rspec?
|
19
|
+
m.directory(File.join('spec/controllers'))
|
20
|
+
m.directory(File.join('spec/models'))
|
21
|
+
m.directory(File.join('spec/helpers'))
|
22
|
+
m.directory(File.join('spec/views'))
|
23
|
+
m.directory(File.join("spec/views/#{table_name}"))
|
24
|
+
|
25
|
+
# Controllers
|
26
|
+
m.template "spec/polls_controller_spec.rb", File.join('spec/controllers', "#{table_name}_controller_spec.rb")
|
27
|
+
m.template "spec/polls_routing_spec.rb", File.join('spec/controllers', "#{table_name}_routing_spec.rb")
|
28
|
+
|
29
|
+
# Models
|
30
|
+
m.template "spec/poll_spec.rb", File.join('spec/models', "#{table_name.singularize}_spec.rb")
|
31
|
+
m.template "spec/poll_vote_spec.rb", File.join('spec/models', "#{table_name.singularize}_vote_spec.rb")
|
32
|
+
|
33
|
+
# Helpers
|
34
|
+
m.template "spec/polls_helper_spec.rb", File.join('spec/helpers', "#{table_name}_helper_spec.rb")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Controllers
|
38
|
+
m.template "polls_controller.rb", File.join('app/controllers', "#{table_name}_controller.rb")
|
39
|
+
|
40
|
+
# Models
|
41
|
+
m.template "poll.rb", File.join('app/models', "#{table_name.singularize}.rb")
|
42
|
+
m.template "poll_vote.rb", File.join('app/models', "#{table_name.singularize}_vote.rb")
|
43
|
+
|
44
|
+
# Helpers
|
45
|
+
m.template "polls_helper.rb", File.join('app/helpers', "#{table_name}_helper.rb")
|
46
|
+
|
47
|
+
# Migrations
|
48
|
+
m.migration_template "create_pollster_tables.rb", "db/migrate", :migration_file_name => "create_pollster_tables"
|
49
|
+
|
50
|
+
# Views
|
51
|
+
for view in views
|
52
|
+
new_name = (view == "_poll") ? "_#{object_name}" : view
|
53
|
+
m.template "views/#{view}.html.erb", File.join("app/views/#{table_name}", "#{new_name}.html.erb")
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def table_name
|
60
|
+
class_name.tableize
|
61
|
+
end
|
62
|
+
|
63
|
+
def model_name
|
64
|
+
class_name.demodulize
|
65
|
+
end
|
66
|
+
|
67
|
+
def object_name
|
68
|
+
table_name.singularize
|
69
|
+
end
|
70
|
+
|
71
|
+
def install_routes(m)
|
72
|
+
route_string = ":#{table_name}, :member => { :vote => :post }"
|
73
|
+
def route_string.to_sym; to_s; end
|
74
|
+
def route_string.inspect; to_s; end
|
75
|
+
m.route_resources route_string
|
76
|
+
end
|
77
|
+
|
78
|
+
def has_rspec?
|
79
|
+
spec_dir = File.join(RAILS_ROOT, 'spec')
|
80
|
+
options[:rspec] ||= (File.exist?(spec_dir) && File.directory?(spec_dir)) unless (options[:rspec] == false)
|
81
|
+
end
|
82
|
+
|
83
|
+
def views
|
84
|
+
%w[ _current_results _final_results _option_form _poll _vote edit index new ]
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def banner
|
90
|
+
"Usage: #{$0} #{spec.name} ModelName"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class CreatePollsterTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
t.string :name
|
5
|
+
t.text :description
|
6
|
+
t.text :options
|
7
|
+
t.date :ends_at
|
8
|
+
t.text :string
|
9
|
+
t.integer :created_by_id
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :<%= object_name %>_votes do |t|
|
15
|
+
t.integer :user_id
|
16
|
+
t.string :vote
|
17
|
+
t.integer :<%= object_name %>_id
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.down
|
24
|
+
drop_table :<%= table_name %>
|
25
|
+
drop_table :<%= table_name %>_votes
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
class <%= class_name %> < ActiveRecord::Base
|
2
|
+
|
3
|
+
serialize :options
|
4
|
+
|
5
|
+
has_many :votes, :class_name => "<%= class_name %>Vote", :dependent => :destroy
|
6
|
+
has_many :voters, :through => :votes, :source => :user
|
7
|
+
belongs_to :author, :foreign_key => 'created_by_id', :class_name => 'User'
|
8
|
+
|
9
|
+
validates_presence_of :ends_at, :name, :created_by_id
|
10
|
+
|
11
|
+
|
12
|
+
def can_by_voted_on_by(user)
|
13
|
+
active? && !has_already_voted?(user)
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_already_voted?(user)
|
17
|
+
voters.include?(user)
|
18
|
+
end
|
19
|
+
|
20
|
+
def active?
|
21
|
+
Time.now < ends_at.end_of_day
|
22
|
+
end
|
23
|
+
|
24
|
+
def visible?
|
25
|
+
Date.today < (ends_at + 7.days)
|
26
|
+
end
|
27
|
+
|
28
|
+
def winner
|
29
|
+
return nil if active?
|
30
|
+
|
31
|
+
index = current_results_percentages.index(winning_percentage)
|
32
|
+
options[index]
|
33
|
+
end
|
34
|
+
|
35
|
+
def winners
|
36
|
+
return nil if active? || !ends_in_tie?
|
37
|
+
|
38
|
+
winners = []
|
39
|
+
percentage = winning_percentage
|
40
|
+
|
41
|
+
current_results_percentages.each_with_index do |p, index|
|
42
|
+
winners << options[index] if p == winning_percentage
|
43
|
+
end
|
44
|
+
|
45
|
+
winners
|
46
|
+
end
|
47
|
+
|
48
|
+
def ends_in_tie?
|
49
|
+
percentage = winning_percentage
|
50
|
+
current_results_percentages.select{|p| p == percentage}.size > 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def winning_percentage
|
54
|
+
current_results_percentages.sort.reverse.first
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.visible
|
58
|
+
all.select{|p| p.visible?}
|
59
|
+
end
|
60
|
+
|
61
|
+
def current_results_percentages
|
62
|
+
options.inject([]) do |memo, option|
|
63
|
+
num_votes = num_votes_for(option)
|
64
|
+
memo << percentage_of_votes_for(option)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def num_votes_for(option)
|
69
|
+
return 0 unless has_votes?
|
70
|
+
votes.select{|v| v.vote == option}.size
|
71
|
+
end
|
72
|
+
|
73
|
+
def pie_legend
|
74
|
+
legend = []
|
75
|
+
|
76
|
+
options.each_with_index do |option, index|
|
77
|
+
legend << "%23#{index + 1} (#{formatted_percentage_of_votes_for(option)})"
|
78
|
+
end
|
79
|
+
|
80
|
+
legend
|
81
|
+
end
|
82
|
+
|
83
|
+
def total_votes
|
84
|
+
votes.size.to_f
|
85
|
+
end
|
86
|
+
|
87
|
+
def percentage_of_votes_for(option)
|
88
|
+
return 0.0 unless has_votes?
|
89
|
+
num_votes_for(option) / total_votes
|
90
|
+
end
|
91
|
+
|
92
|
+
def formatted_percentage_of_votes_for(option)
|
93
|
+
"#{sprintf("%0.0f", percentage_of_votes_for(option) * 100)}%"
|
94
|
+
end
|
95
|
+
|
96
|
+
def has_votes?
|
97
|
+
total_votes > 0
|
98
|
+
end
|
99
|
+
|
100
|
+
def options=(arr)
|
101
|
+
write_attribute(:options, [*arr].map{|x| x["options"]})
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class <%= class_name.pluralize %>Controller < ApplicationController
|
2
|
+
|
3
|
+
before_filter :load_items
|
4
|
+
|
5
|
+
def load_items
|
6
|
+
@<%= object_name %> = <%= class_name %>.find(params[:id]) if params[:id]
|
7
|
+
end
|
8
|
+
|
9
|
+
def index
|
10
|
+
@<%= object_name %>s = <%= class_name %>.visible
|
11
|
+
end
|
12
|
+
|
13
|
+
def show
|
14
|
+
redirect_to <%= object_name %>s_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def new
|
18
|
+
@<%= object_name %> = <%= class_name %>.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def edit
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
@<%= object_name %> = <%= class_name %>.new(params[:<%= object_name %>])
|
26
|
+
|
27
|
+
if @<%= object_name %>.save
|
28
|
+
flash[:notice] = "<%= class_name %> successfully created"
|
29
|
+
redirect_to <%= object_name %>s_path
|
30
|
+
else
|
31
|
+
render :action => "new"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def update
|
36
|
+
if @<%= object_name %>.update_attributes(params[:<%= object_name %>])
|
37
|
+
flash[:notice] = '<%= class_name %> was successfully updated.'
|
38
|
+
redirect_to <%= object_name %>s_path
|
39
|
+
else
|
40
|
+
flash[:error] = "An error occurred"
|
41
|
+
render :action => "edit"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
@<%= object_name %>.destroy
|
47
|
+
redirect_to <%= object_name %>s_path
|
48
|
+
end
|
49
|
+
|
50
|
+
def vote
|
51
|
+
unless @<%= object_name %>.has_already_voted?(current_user)
|
52
|
+
v = @<%= object_name %>.votes.build(:user => current_user, :vote => params[:<%= object_name %>]["vote"])
|
53
|
+
|
54
|
+
if v.save
|
55
|
+
flash[:notice] = "Vote cast!"
|
56
|
+
else
|
57
|
+
flash[:error] = "Something happened..."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
redirect_to <%= object_name %>s_path
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
module <%= class_name %>Attributes
|
4
|
+
def valid_attributes
|
5
|
+
{
|
6
|
+
:name => "foo",
|
7
|
+
:description => "foo",
|
8
|
+
:options => ["first", "second", "third"],
|
9
|
+
:ends_at => Date.parse("2009-01-09"),
|
10
|
+
:created_at => Date.parse("2009-01-01"),
|
11
|
+
:updated_at => Date.parse("2009-01-01"),
|
12
|
+
:created_by_id => 1
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe <%= class_name %> do
|
18
|
+
|
19
|
+
include <%= class_name %>Attributes
|
20
|
+
|
21
|
+
before do
|
22
|
+
@<%= object_name %> = <%= class_name %>.create!(valid_attributes)
|
23
|
+
@<%= object_name %>.stub!(:votes => [])
|
24
|
+
@author = mock_model(User)
|
25
|
+
@user = mock_model(User)
|
26
|
+
|
27
|
+
@<%= object_name %>.stub!(:author => @author)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be valid" do
|
31
|
+
@<%= object_name %>.valid?.should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should serialize #options" do
|
35
|
+
@<%= object_name %>.options.is_a?(Array).should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should know the total number of votes cast" do
|
39
|
+
vote = mock_model(<%= class_name %>Vote)
|
40
|
+
@<%= object_name %>.stub!(:votes => [vote])
|
41
|
+
|
42
|
+
@<%= object_name %>.total_votes.should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should know how to shave the options yak" do
|
46
|
+
@<%= object_name %>.options = [{"options" => "first"}, {"options" => "second"}, {"options" => "third"}]
|
47
|
+
@<%= object_name %>.save
|
48
|
+
@<%= object_name %>.options.should == ["first", "second", "third"]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should be visible for a week after its end date" do
|
52
|
+
Date.stub!(:today => Date.parse("2009-01-09"))
|
53
|
+
@<%= object_name %>.stub!(:ends_at => Date.parse("2009-01-07"))
|
54
|
+
|
55
|
+
@<%= object_name %>.visible?.should be_true
|
56
|
+
|
57
|
+
@<%= object_name %>.stub!(:ends_at => Date.parse("2009-01-01"))
|
58
|
+
@<%= object_name %>.visible?.should be_false
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be able to find all visible <%= class_name %>s" do
|
63
|
+
<%= object_name %>_1 = mock_model(<%= class_name %>, :visible? => true)
|
64
|
+
<%= object_name %>_2 = mock_model(<%= class_name %>, :visible? => false)
|
65
|
+
<%= class_name %>.stub!(:all => [<%= object_name %>_1, <%= object_name %>_2])
|
66
|
+
|
67
|
+
<%= class_name %>.visible.should == [<%= object_name %>_1]
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
describe " - Associations" do
|
72
|
+
it "should know about votes" do
|
73
|
+
@<%= object_name %>.votes.should == []
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should know about voters" do
|
77
|
+
@<%= object_name %>.voters.should == []
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should know about its author" do
|
81
|
+
@<%= object_name %>.author.should == @author
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe " - Required attributes" do
|
87
|
+
it "should require name" do
|
88
|
+
@<%= object_name %>.name = nil
|
89
|
+
@<%= object_name %>.valid?.should be_false
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should require an end_date" do
|
93
|
+
@<%= object_name %>.ends_at = nil
|
94
|
+
@<%= object_name %>.valid?.should be_false
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should require an author" do
|
98
|
+
@<%= object_name %>.created_by_id = nil
|
99
|
+
@<%= object_name %>.valid?.should be_false
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
describe " that has no votes" do
|
105
|
+
before do
|
106
|
+
@<%= object_name %>.stub!(:votes => [])
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should know that it has no votes" do
|
110
|
+
@<%= object_name %>.has_votes?.should be_false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe " that has votes" do
|
115
|
+
before do
|
116
|
+
@vote = mock_model(<%= class_name %>Vote)
|
117
|
+
@<%= object_name %>.stub!(:votes => [@vote])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should know that it has votes" do
|
121
|
+
@<%= object_name %>.has_votes?.should be_true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should know how to calculate the current results" do
|
125
|
+
@<%= object_name %>.stub!(:options => ["first", "second", "third"])
|
126
|
+
@<%= object_name %>.stub!(:num_votes_for)
|
127
|
+
@<%= object_name %>.stub!(:percentage_of_votes_for).with("first").and_return(10.0)
|
128
|
+
@<%= object_name %>.stub!(:percentage_of_votes_for).with("second").and_return(60.0)
|
129
|
+
@<%= object_name %>.stub!(:percentage_of_votes_for).with("third").and_return(30.00)
|
130
|
+
|
131
|
+
@<%= object_name %>.current_results_percentages.should == [10.0, 60.0, 30.0]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should know how to get a vote count for an option" do
|
135
|
+
vote_1 = mock_model(<%= class_name %>Vote, :vote => "first")
|
136
|
+
vote_2 = mock_model(<%= class_name %>Vote, :vote => "second")
|
137
|
+
vote_3 = mock_model(<%= class_name %>Vote, :vote => "first")
|
138
|
+
@<%= object_name %>.stub!(:votes => [vote_1, vote_2, vote_3])
|
139
|
+
|
140
|
+
@<%= object_name %>.num_votes_for("first").should == 2
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should be able to generate a legend for the results chart" do
|
144
|
+
@<%= object_name %>.stub!(:options => ["first", "second", "third"])
|
145
|
+
@<%= object_name %>.stub!(:formatted_percentage_of_votes_for).with("first").and_return("10%")
|
146
|
+
@<%= object_name %>.stub!(:formatted_percentage_of_votes_for).with("second").and_return("60%")
|
147
|
+
@<%= object_name %>.stub!(:formatted_percentage_of_votes_for).with("third").and_return("20%")
|
148
|
+
|
149
|
+
@<%= object_name %>.pie_legend.should == ["%231 (10%)", "%232 (60%)", "%233 (20%)"]
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should be able to calculate the percentage of votes cast for an option" do
|
153
|
+
@<%= object_name %>.should_receive(:num_votes_for).with("first").and_return(10)
|
154
|
+
@<%= object_name %>.stub!(:total_votes => 100.0)
|
155
|
+
|
156
|
+
@<%= object_name %>.percentage_of_votes_for("first").should == 0.1
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should be able to format the percentage of votes cast for an option" do
|
160
|
+
@<%= object_name %>.should_receive(:num_votes_for).with("first").and_return(10)
|
161
|
+
@<%= object_name %>.stub!(:total_votes => 100.0)
|
162
|
+
|
163
|
+
@<%= object_name %>.formatted_percentage_of_votes_for("first").should == "10%"
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should know if a User has already voted" do
|
167
|
+
user = mock_model(User)
|
168
|
+
user2 = mock_model(User)
|
169
|
+
@<%= object_name %>.stub!(:voters => [user])
|
170
|
+
|
171
|
+
@<%= object_name %>.has_already_voted?(user).should be_true
|
172
|
+
@<%= object_name %>.has_already_voted?(user2).should be_false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe " that has not yet reached its end date" do
|
177
|
+
before do
|
178
|
+
@<%= object_name %>.ends_at = 3.days.from_now
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should be considered active" do
|
182
|
+
@<%= object_name %>.active?.should be_true
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should allow voting by a new voter" do
|
186
|
+
user = mock_model(User)
|
187
|
+
@<%= object_name %>.stub!(:has_already_voted? => false)
|
188
|
+
|
189
|
+
@<%= object_name %>.can_by_voted_on_by(user).should be_true
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
describe " that is on its last day of voting" do
|
195
|
+
it "should know that it's still open" do
|
196
|
+
date = Date.parse("2009-01-10")
|
197
|
+
@<%= object_name %>.stub!(:ends_at => date)
|
198
|
+
Time.stub!(:now => date.end_of_day - 1.second)
|
199
|
+
|
200
|
+
@<%= object_name %>.active?.should be_true
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe " that has passed its end date" do
|
205
|
+
before do
|
206
|
+
@<%= object_name %>.ends_at = Date.yesterday
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not be considered active" do
|
210
|
+
@<%= object_name %>.active?.should be_false
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not allow voting by a new voter" do
|
214
|
+
user = mock_model(User)
|
215
|
+
@<%= object_name %>.stub!(:has_already_voted? => false)
|
216
|
+
|
217
|
+
@<%= object_name %>.can_by_voted_on_by(user).should be_false
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should know who the winner is" do
|
221
|
+
@<%= object_name %>.stub!(:options => ["first", "second", "third"])
|
222
|
+
@<%= object_name %>.stub!(:winning_percentage => 0.9)
|
223
|
+
@<%= object_name %>.stub!(:current_results_percentages => [0.0, 0.9, 0.1])
|
224
|
+
|
225
|
+
@<%= object_name %>.winner.should == "second"
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should know what the winning percentage was" do
|
229
|
+
@<%= object_name %>.stub!(:current_results_percentages => [0.4, 0.5, 0.1])
|
230
|
+
@<%= object_name %>.winning_percentage.should == 0.5
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
describe " and ends in a tie" do
|
235
|
+
before do
|
236
|
+
@<%= object_name %>.stub!(:options => ["first", "second", "third"])
|
237
|
+
@<%= object_name %>.stub!(:winning_percentage => 0.4)
|
238
|
+
@<%= object_name %>.stub!(:current_results_percentages => [0.4, 0.4, 0.2])
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should know that it ends in a tie" do
|
242
|
+
@<%= object_name %>.ends_in_tie?.should be_true
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should know which options tied" do
|
246
|
+
@<%= object_name %>.winners.should == ["first", "second"]
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe <%= class_name %>Vote do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@vote = <%= class_name %>Vote.new(:user_id => 1, :<%= object_name %>_id => 1)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be valid" do
|
10
|
+
@vote.valid?.should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should know about the User" do
|
14
|
+
@vote.should respond_to(:user)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should know about the <%= class_name %>" do
|
18
|
+
@vote.should respond_to(:<%= object_name %>)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|