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 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,6 @@
1
+ class <%= class_name %>Vote < ActiveRecord::Base
2
+
3
+ belongs_to :user
4
+ belongs_to :<%= object_name %>
5
+
6
+ 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,9 @@
1
+ module <%= class_name.pluralize %>Helper
2
+
3
+ def add_option_link(<%= object_name %>, name)
4
+ link_to_function name do |page|
5
+ page.insert_html :bottom, :options, :partial => 'option_form', :locals => {:option => []}
6
+ end
7
+ end
8
+
9
+ 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