mdarby-pollster 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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