voter_love 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ Gemfile.lock
2
+ .bundle/
3
+ log/*.log
4
+ pkg/
5
+ test/dummy/db/*.sqlite3
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in voter_love.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'ruby-debug19', :require => 'ruby-debug'
data/Gemfile.lock ADDED
@@ -0,0 +1,114 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ voter_love (0.0.1)
5
+ rails (~> 3.1.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionmailer (3.1.0)
11
+ actionpack (= 3.1.0)
12
+ mail (~> 2.3.0)
13
+ actionpack (3.1.0)
14
+ activemodel (= 3.1.0)
15
+ activesupport (= 3.1.0)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ i18n (~> 0.6)
19
+ rack (~> 1.3.2)
20
+ rack-cache (~> 1.0.3)
21
+ rack-mount (~> 0.8.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.0.0)
24
+ activemodel (3.1.0)
25
+ activesupport (= 3.1.0)
26
+ bcrypt-ruby (~> 3.0.0)
27
+ builder (~> 3.0.0)
28
+ i18n (~> 0.6)
29
+ activerecord (3.1.0)
30
+ activemodel (= 3.1.0)
31
+ activesupport (= 3.1.0)
32
+ arel (~> 2.2.1)
33
+ tzinfo (~> 0.3.29)
34
+ activeresource (3.1.0)
35
+ activemodel (= 3.1.0)
36
+ activesupport (= 3.1.0)
37
+ activesupport (3.1.0)
38
+ multi_json (~> 1.0)
39
+ arel (2.2.1)
40
+ bcrypt-ruby (3.0.1)
41
+ builder (3.0.0)
42
+ diff-lcs (1.1.3)
43
+ erubis (2.7.0)
44
+ generator_spec (0.8.4)
45
+ rails (>= 3.0, < 4.0)
46
+ rspec-rails
47
+ hike (1.2.1)
48
+ i18n (0.6.0)
49
+ mail (2.3.0)
50
+ i18n (>= 0.4.0)
51
+ mime-types (~> 1.16)
52
+ treetop (~> 1.4.8)
53
+ mime-types (1.16)
54
+ multi_json (1.0.3)
55
+ polyglot (0.3.2)
56
+ rack (1.3.3)
57
+ rack-cache (1.0.3)
58
+ rack (>= 0.4)
59
+ rack-mount (0.8.3)
60
+ rack (>= 1.0.0)
61
+ rack-ssl (1.3.2)
62
+ rack
63
+ rack-test (0.6.1)
64
+ rack (>= 1.0)
65
+ rails (3.1.0)
66
+ actionmailer (= 3.1.0)
67
+ actionpack (= 3.1.0)
68
+ activerecord (= 3.1.0)
69
+ activeresource (= 3.1.0)
70
+ activesupport (= 3.1.0)
71
+ bundler (~> 1.0)
72
+ railties (= 3.1.0)
73
+ railties (3.1.0)
74
+ actionpack (= 3.1.0)
75
+ activesupport (= 3.1.0)
76
+ rack-ssl (~> 1.3.2)
77
+ rake (>= 0.8.7)
78
+ rdoc (~> 3.4)
79
+ thor (~> 0.14.6)
80
+ rake (0.9.2)
81
+ rdoc (3.9.4)
82
+ rspec (2.5.0)
83
+ rspec-core (~> 2.5.0)
84
+ rspec-expectations (~> 2.5.0)
85
+ rspec-mocks (~> 2.5.0)
86
+ rspec-core (2.5.2)
87
+ rspec-expectations (2.5.0)
88
+ diff-lcs (~> 1.1.2)
89
+ rspec-mocks (2.5.0)
90
+ rspec-rails (2.5.0)
91
+ actionpack (~> 3.0)
92
+ activesupport (~> 3.0)
93
+ railties (~> 3.0)
94
+ rspec (~> 2.5.0)
95
+ sprockets (2.0.0)
96
+ hike (~> 1.2)
97
+ rack (~> 1.0)
98
+ tilt (!= 1.3.0, ~> 1.1)
99
+ sqlite3 (1.3.4)
100
+ thor (0.14.6)
101
+ tilt (1.3.3)
102
+ treetop (1.4.10)
103
+ polyglot
104
+ polyglot (>= 0.3.1)
105
+ tzinfo (0.3.29)
106
+
107
+ PLATFORMS
108
+ ruby
109
+
110
+ DEPENDENCIES
111
+ generator_spec (~> 0.8.2)
112
+ rspec (~> 2.5.0)
113
+ sqlite3
114
+ voter_love!
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 YOURNAME
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.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = Voter Love
2
+
3
+ An easy to use Rails 3.1 voting Gem
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'VoterLove'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ Bundler::GemHelper.install_tasks
24
+
25
+ require 'rspec/core/rake_task'
26
+ RSpec::Core::RakeTask.new(:spec)
27
+
28
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ class CreateVoterLoveTables < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :votes do |t|
4
+ t.string :votable_type
5
+ t.integer :votable_id
6
+ t.string :voter_type
7
+ t.integer :voter_id
8
+ t.boolean :up_vote, :null => false
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :votes, [:votable_type, :votable_id]
14
+ add_index :votes, [:voter_type, :voter_id]
15
+ add_index :votes, [:votable_type, :votable_id, :voter_type, :voter_id], :name => "unique_voters", :unique => true
16
+ end
17
+
18
+ def self.down
19
+ remove_index :votes, :column => [:votable_type, :votable_id]
20
+ remove_index :votes, :column => [:voter_type, :voter_id]
21
+ remove_index :votes, :name => "unique_voters"
22
+
23
+ drop_table :votes
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ require 'rails/generators/migration'
2
+ require 'rails/generators/active_record'
3
+
4
+ class VoterLoveGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ desc "Generates a migration for the Vote model"
8
+
9
+ def self.source_root
10
+ @source_root ||= File.dirname(__FILE__) + '/templates'
11
+ end
12
+
13
+ def self.next_migration_number(path)
14
+ ActiveRecord::Generators::Base.next_migration_number(path)
15
+ end
16
+
17
+ def generate_migration
18
+ migration_template 'migration.rb', 'db/migrate/create_voter_love_tables'
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :voter_love do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,29 @@
1
+ module VoterLove
2
+ module Exceptions
3
+ class AlreadyVotedError < StandardError
4
+ attr_reader :up_vote
5
+
6
+ def initialize(up_vote)
7
+ vote = if up_vote
8
+ "up voted"
9
+ else
10
+ "down voted"
11
+ end
12
+
13
+ super "The votable was already #{vote} by the voter."
14
+ end
15
+ end
16
+
17
+ class NotVotedError < StandardError
18
+ def initialize
19
+ super "The votable was not voted by the voter."
20
+ end
21
+ end
22
+
23
+ class InvalidVotableError < StandardError
24
+ def initialize
25
+ super "Invalid votable."
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module VoterLove
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,20 @@
1
+ module VoterLove
2
+ module Votable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :votes, :class_name => "VoterLove::Votes", :as => :votable
7
+ end
8
+
9
+ module ClassMethods
10
+ def votable?
11
+ true
12
+ end
13
+ end
14
+
15
+ # Returns the difference of down and up votes.
16
+ def score
17
+ self.up_votes - self.down_votes
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,138 @@
1
+ module VoterLove
2
+ module Voter
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :votes, :class_name => "VoterLove::Vote", :as => :voter
7
+ end
8
+
9
+ module ClassMethods
10
+ def voter?
11
+ true
12
+ end
13
+ end
14
+
15
+ # Up vote any "votable" object.
16
+ # Raises an AlreadyVotedError if the voter already voted on the object.
17
+ def up_vote(votable)
18
+ is_votable?(votable)
19
+
20
+ vote = get_vote(votable)
21
+
22
+ if vote
23
+ if vote.up_vote
24
+ raise Exceptions::AlreadyVotedError.new(true)
25
+ end
26
+ vote.up_vote = true
27
+ votable.down_votes -= 1
28
+ self.down_votes -= 1 if has_attribute?(:down_votes)
29
+ end
30
+ else
31
+ vote = Vote.create(:votable => votable, :voter => self, :up_vote => true)
32
+ end
33
+
34
+ votable.up_votes += 1
35
+ self.up_votes += 1 if has_attribute?(:up_votes)
36
+
37
+ Vote.transaction do
38
+ save
39
+ votable.save
40
+ vote.save
41
+ end
42
+
43
+ true
44
+ end
45
+
46
+ # Up vote any "votable" object without raising an error. Vote is ignored.
47
+ def up_vote!(votable)
48
+ begin
49
+ up_vote(votable)
50
+ success = true
51
+ rescue Exceptions::AlreadyVotedError
52
+ success = false
53
+ end
54
+ success
55
+ end
56
+
57
+ # Down vote a "votable" object.
58
+ # Raises an AlreadyVotedError if the voter already voted on the object.
59
+ def down_vote(votable)
60
+ is_votable?(votable)
61
+
62
+ vote = get_vote(votable)
63
+
64
+ if vote
65
+ unless vote.up_vote
66
+ raise Exceptions::AlreadyVotedError.new(false)
67
+ else
68
+ vote.up_vote = false
69
+ votable.up_votes -= 1
70
+ self.up_votes -= 1 if has_attribute?(:up_votes)
71
+ end
72
+ else
73
+ vote = Vote.create(:votable => votable, :voter => self, :up_vote => false)
74
+ end
75
+
76
+ votable.down_votes += 1
77
+ self.down_votes += 1 if has_attribute?(:down_votes)
78
+
79
+ Vote.transaction do
80
+ save
81
+ votable.save
82
+ vote.save
83
+ end
84
+
85
+ true
86
+ end
87
+
88
+ # Down vote a "votable" object without raising an error. Vote is ignored.
89
+ def down_vote!(votable)
90
+ begin
91
+ down_vote(votable)
92
+ success = true
93
+ rescue Exceptions::AlreadyVotedError
94
+ success = false
95
+ end
96
+ success
97
+ end
98
+
99
+ # Returns true if the voter voted for the "votable".
100
+ def voted?(votable)
101
+ is_votable?(votable)
102
+ vote = get_vote(votable)
103
+ !vote.nil?
104
+ end
105
+
106
+ # Returns true if the voter up voted the "votable".
107
+ def up_voted?(votable)
108
+ is_votable?(votable)
109
+ vote = get_vote(votable)
110
+ return false if vote.nil?
111
+ return true if vote.has_attribute?(:up_vote) && vote.up_vote
112
+ false
113
+ end
114
+
115
+ # Returns true if the voter down voted the "votable".
116
+ def down_voted?(votable)
117
+ is_votable?(votable)
118
+ vote = get_vote(votable)
119
+ return false if vote.nil?
120
+ return true if vote.has_attribute?(:up_vote) && !vote.up_vote
121
+ false
122
+ end
123
+
124
+ private
125
+
126
+ def get_vote(votable)
127
+ Vote.where(
128
+ :votable_type => votable.class.to_s,
129
+ :votable_id => votable.id,
130
+ :voter_type => self.class.to_s,
131
+ :voter_id => self.id).try(:first)
132
+ end
133
+
134
+ def is_votable?(votable)
135
+ raise Exceptions::InvalidVotableError unless votable.class.votable?
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,8 @@
1
+ module VoterLove
2
+ class Votes < ActiveRecord::Base
3
+ attr_accessible :votable, :voter, :up_vote
4
+
5
+ belongs_to :votable, :polymorphic => true
6
+ belongs_to :voter, :polymorphic => true
7
+ end
8
+ end
data/lib/voter_love.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'voter_love/votes'
2
+ require 'voter_love/votable'
3
+ require 'voter_love/voter'
4
+ require 'voter_love/exceptions'
5
+
6
+ module VoterLove
7
+ def votable?
8
+ false
9
+ end
10
+
11
+ def voter?
12
+ false
13
+ end
14
+
15
+ # add this to the model you want to be able to vote on.
16
+ # Example:
17
+ # class Links < ActiveRecord::Base
18
+ # acts_as_votable
19
+ # end
20
+ def acts_as_votable
21
+ include Votable
22
+ end
23
+
24
+ def acts_as_voter
25
+ include Voter
26
+ end
27
+ end
28
+
29
+ ActiveRecord::Base.extend VoterLove
data/spec/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: voter_love.sqlite3
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: voter_love.sqlite3
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'action_controller'
3
+ require 'generator_spec/test_case'
4
+ require 'generators/voter_love/voter_love_generator'
5
+
6
+ describe VoterLoveGenerator do
7
+ include GeneratorSpec::TestCase
8
+ destination File.expand_path("/tmp", __FILE__)
9
+ tests VoterLoveGenerator
10
+
11
+ before do
12
+ prepare_destination
13
+ run_generator
14
+ end
15
+
16
+ specify do
17
+ destination_root.should have_structure {
18
+ directory "db" do
19
+ directory "migrate" do
20
+ migration "create_voter_love_tables" do
21
+ contains "class CreateVoterLoveTables"
22
+ contains "create_table :votes"
23
+ end
24
+ end
25
+ end
26
+ }
27
+ end
28
+ end
@@ -0,0 +1,236 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Voter Love" do
4
+ before(:each) do
5
+ @votable = VotableModel.create(:name => "Votable 1")
6
+ @voter = VoterModel.create(:name => "Voter 1")
7
+ end
8
+
9
+ it "should create a votable instance" do
10
+ @votable.class.should == VotableModel
11
+ @votable.class.votable?.should == true
12
+ end
13
+
14
+ it "should create a voter instance" do
15
+ @voter.class.should == VoterModel
16
+ @voter.class.voter?.should == true
17
+ end
18
+
19
+ it "should get correct vote summary" do
20
+ @voter.up_vote(@votable).should == true
21
+ @votable.votes.should == 1
22
+ @voter.down_vote(@votable).should == true
23
+ @votable.votes.should == -1
24
+ @voter.unvote(@votable).should == true
25
+ @votable.votes.should == 0
26
+ end
27
+
28
+ it "votable should have up vote votes" do
29
+ @votable.votes.length.should == 0
30
+ @voter.up_vote(@votable)
31
+ @votable.votes.reload.length.should == 1
32
+ @votable.votes[0].up_vote?.should be_true
33
+ end
34
+
35
+ it "voter should have up vote votes" do
36
+ @voter.votes.length.should == 0
37
+ @voter.up_vote(@votable)
38
+ @voter.votes.reload.length.should == 1
39
+ @voter.votes[0].up_vote?.should be_true
40
+ end
41
+
42
+ it "votable should have down vote votes" do
43
+ @votable.votes.length.should == 0
44
+ @voter.down_vote(@votable)
45
+ @votable.votes.reload.length.should == 1
46
+ @votable.votes[0].up_vote?.should be_false
47
+ end
48
+
49
+ it "voter should have down vote votes" do
50
+ @voter.votes.length.should == 0
51
+ @voter.down_vote(@votable)
52
+ @voter.votes.reload.length.should == 1
53
+ @voter.votes[0].up_vote?.should be_false
54
+ end
55
+
56
+ describe "up vote" do
57
+ it "should increase up votes of votable by one" do
58
+ @votable.up_votes.should == 0
59
+ @voter.up_vote(@votable)
60
+ @votable.up_votes.should == 1
61
+ end
62
+
63
+ it "should increase up votes of voter by one" do
64
+ @voter.up_votes.should == 0
65
+ @voter.up_vote(@votable)
66
+ @voter.up_votes.should == 1
67
+ end
68
+
69
+ it "should create a voting" do
70
+ VoterLove::Votes.count.should == 0
71
+ @voter.up_vote(@votable)
72
+ VoterLove::Votes.count.should == 1
73
+ voting = VoterLove::Votes.first
74
+ voting.votable.should == @votable
75
+ voting.voter.should == @voter
76
+ voting.up_vote.should == true
77
+ end
78
+
79
+ it "should only allow a voter to up vote a votable once" do
80
+ @voter.up_vote(@votable)
81
+ lambda { @voter.up_vote(@votable) }.should raise_error(VoterLove::Exceptions::AlreadyVotedError)
82
+ end
83
+
84
+ it "should only allow a voter to up vote a votable once without raising an error" do
85
+ @voter.up_vote!(@votable)
86
+ lambda {
87
+ @voter.up_vote!(@votable).should == false
88
+ }.should_not raise_error(VoterLove::Exceptions::AlreadyVotedError)
89
+ VoterLove::Votes.count.should == 1
90
+ end
91
+
92
+ it "should change a down vote to an up vote" do
93
+ @voter.down_vote(@votable)
94
+ @votable.up_votes.should == 0
95
+ @votable.down_votes.should == 1
96
+ @voter.up_votes.should == 0
97
+ @voter.down_votes.should == 1
98
+ VoterLove::Votes.count.should == 1
99
+ VoterLove::Votes.first.up_vote.should be_false
100
+ @voter.up_vote(@votable)
101
+ @votable.up_votes.should == 1
102
+ @votable.down_votes.should == 0
103
+ @voter.up_votes.should == 1
104
+ @voter.down_votes.should == 0
105
+ VoterLove::Votes.count.should == 1
106
+ VoterLove::Votes.first.up_vote.should be_true
107
+ end
108
+
109
+ it "should allow up votes from different voters" do
110
+ @voter2 = VoterModel.create(:name => "Voter 2")
111
+ @voter.up_vote(@votable)
112
+ @voter2.up_vote(@votable)
113
+ @votable.up_votes.should == 2
114
+ VoterLove::Votes.count.should == 2
115
+ end
116
+
117
+ it "should raise an error for an invalid votable" do
118
+ invalid_votable = InvalidVotableModel.create
119
+ lambda { @voter.up_vote(invalid_votable) }.should raise_error(VoterLove::Exceptions::InvalidVotableError)
120
+ end
121
+
122
+ it "should check if voter up voted votable" do
123
+ @voter.up_vote(@votable)
124
+ @voter.voted?(@votable).should be_true
125
+ @voter.up_voted?(@votable).should be_true
126
+ @voter.down_voted?(@votable).should be_false
127
+ end
128
+ end
129
+
130
+ describe "vote down" do
131
+ it "should decrease down votes of votable by one" do
132
+ @votable.down_votes.should == 0
133
+ @voter.down_vote(@votable)
134
+ @votable.down_votes.should == 1
135
+ end
136
+
137
+ it "should decrease down votes of voter by one" do
138
+ @voter.down_votes.should == 0
139
+ @voter.down_vote(@votable)
140
+ @voter.down_votes.should == 1
141
+ end
142
+
143
+ it "should create a voting" do
144
+ VoterLove::Votes.count.should == 0
145
+ @voter.down_vote(@votable)
146
+ VoterLove::Votes.count.should == 1
147
+ voting = VoterLove::Votes.first
148
+ voting.votable.should == @votable
149
+ voting.voter.should == @voter
150
+ voting.up_vote.should == false
151
+ end
152
+
153
+ it "should only allow a voter to down vote a votable once" do
154
+ @voter.down_vote(@votable)
155
+ lambda { @voter.down_vote(@votable) }.should raise_error(VoterLove::Exceptions::AlreadyVotedError)
156
+ end
157
+
158
+ it "should only allow a voter to down vote a votable once without raising an error" do
159
+ @voter.down_vote!(@votable)
160
+ lambda {
161
+ @voter.down_vote!(@votable).should == false
162
+ }.should_not raise_error(VoterLove::Exceptions::AlreadyVotedError)
163
+ VoterLove::Votes.count.should == 1
164
+ end
165
+
166
+ it "should change an up vote to a down vote" do
167
+ @voter.up_vote(@votable)
168
+ @votable.up_votes.should == 1
169
+ @votable.down_votes.should == 0
170
+ @voter.up_votes.should == 1
171
+ @voter.down_votes.should == 0
172
+ VoterLove::Votes.count.should == 1
173
+ VoterLove::Votes.first.up_vote.should be_true
174
+ @voter.down_vote(@votable)
175
+ @votable.up_votes.should == 0
176
+ @votable.down_votes.should == 1
177
+ @voter.up_votes.should == 0
178
+ @voter.down_votes.should == 1
179
+ VoterLove::Votes.count.should == 1
180
+ VoterLove::Votes.first.up_vote.should be_false
181
+ end
182
+
183
+ it "should allow down votes from different voters" do
184
+ @voter2 = VoterModel.create(:name => "Voter 2")
185
+ @voter.down_vote(@votable)
186
+ @voter2.down_vote(@votable)
187
+ @votable.down_votes.should == 2
188
+ VoterLove::Votes.count.should == 2
189
+ end
190
+
191
+ it "should raise an error for an invalid votable" do
192
+ invalid_votable = InvalidVotableModel.create
193
+ lambda { @voter.down_vote(invalid_votable) }.should raise_error(VoterLove::Exceptions::InvalidVotableError)
194
+ end
195
+
196
+ it "should check if voter down voted votable" do
197
+ @voter.down_vote(@votable)
198
+ @voter.voted?(@votable).should be_true
199
+ @voter.up_voted?(@votable).should be_false
200
+ @voter.down_voted?(@votable).should be_true
201
+ end
202
+ end
203
+
204
+ describe "unvote" do
205
+ it "should decrease the up votes if up voted before" do
206
+ @voter.up_vote(@votable)
207
+ @votable.up_votes.should == 1
208
+ @voter.up_votes.should == 1
209
+ @voter.unvote(@votable)
210
+ @votable.up_votes.should == 0
211
+ @voter.up_votes.should == 0
212
+ end
213
+
214
+ it "should remove the voting" do
215
+ @voter.up_vote(@votable)
216
+ VoterLove::Votes.count.should == 1
217
+ @voter.unvote(@votable)
218
+ VoterLove::Votes.count.should == 0
219
+ end
220
+
221
+ it "should raise an error if voter didn't vote for the votable" do
222
+ lambda { @voter.unvote(@votable) }.should raise_error(VoterLove::Exceptions::NotVotedError)
223
+ end
224
+
225
+ it "should not raise error if voter didn't vote for the votable and unvote! is called" do
226
+ lambda {
227
+ @voter.unvote!(@votable).should == false
228
+ }.should_not raise_error(VoterLove::Exceptions::NotVotedError)
229
+ end
230
+
231
+ it "should raise an error for an invalid votable" do
232
+ invalid_votable = InvalidVotableModel.create
233
+ lambda { @voter.unvote(invalid_votable) }.should raise_error(VoterLove::Exceptions::InvalidVotableError)
234
+ end
235
+ end
236
+ end
data/spec/models.rb ADDED
@@ -0,0 +1,10 @@
1
+ class VotableModel < ActiveRecord::Base
2
+ acts_as_votable
3
+ end
4
+
5
+ class VoterModel < ActiveRecord::Base
6
+ acts_as_voter
7
+ end
8
+
9
+ class InvalidVotableModel < ActiveRecord::Base
10
+
data/spec/schema.rb ADDED
@@ -0,0 +1,31 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+ create_table :votable_models, :force => true do |t|
3
+ t.string :name
4
+ t.integer :up_votes, :null => false, :default => 0
5
+ t.integer :down_votes, :null => false, :default => 0
6
+ end
7
+
8
+ create_table :voter_models, :force => true do |t|
9
+ t.string :name
10
+ t.integer :up_votes, :null => false, :default => 0
11
+ t.integer :down_votes, :null => false, :default => 0
12
+ end
13
+
14
+ create_table :invalid_votable_models, :force => true do |t|
15
+ t.string :name
16
+ end
17
+
18
+ create_table :votes, :force => true do |t|
19
+ t.string :votable_type
20
+ t.integer :votable_id
21
+ t.string :voter_type
22
+ t.integer :voter_id
23
+ t.boolean :up_vote, :null => false
24
+
25
+ t.timestamps
26
+ end
27
+
28
+ add_index :votes, [:votable_type, :votable_id]
29
+ add_index :votes, [:voter_type, :voter_id]
30
+ add_index :votes, [:votable_type, :votable_id, :voter_type, :voter_id], :name => "unique_voters", :unique => true
31
+ end
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'logger'
4
+ require 'rspec'
5
+ require 'active_record'
6
+ require 'database_cleaner'
7
+
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
9
+ require 'acts_as_votable'
10
+
11
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
12
+ ActiveRecord::Base.configurations = YAML::load_file(File.dirname(__FILE__) + '/database.yml')
13
+ ActiveRecord::Base.establish_connection(ENV['DB'] || 'sqlite3')
14
+
15
+ ActiveRecord::Base.silence do
16
+ ActiveRecord::Migration.verbose = false
17
+
18
+ load(File.dirname(__FILE__) + '/schema.rb')
19
+ load(File.dirname(__FILE__) + '/models.rb')
20
+ end
21
+
22
+ RSpec.configure do |config|
23
+ config.filter_run :focus => true
24
+ config.run_all_when_everything_filtered = true
25
+ config.filter_run_excluding :exclude => true
26
+
27
+ config.mock_with :rspec
28
+
29
+ config.before(:suite) do
30
+ DatabaseCleaner.strategy = :truncation
31
+ DatabaseCleaner.clean
32
+ end
33
+
34
+ config.after(:each) do
35
+ DatabaseCleaner.clean
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "voter_love/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "voter_love"
9
+ s.version = VoterLove::VERSION
10
+ s.authors = ["Karl Gusner"]
11
+ s.email = ["karlgusner@gmail.com"]
12
+ s.homepage = "https://github.com/ramz15/voter_love"
13
+ s.summary = "An easy to use voting gem for Rails 3"
14
+ s.description = "The voter_love Gem allows users to easily vote on objects"
15
+
16
+ s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
17
+ s.test_files = Dir["test/**/*"]
18
+
19
+ s.add_dependency "rails", "~> 3.1.0"
20
+
21
+ s.add_development_dependency "sqlite3"
22
+ s.add_development_dependency "rspec", "~> 2.5.0"
23
+ s.add_development_dependency "generator_spec", "~> 0.8.2"
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
27
+ s.require_path = 'lib'
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: voter_love
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Karl Gusner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-18 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &2157386880 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2157386880
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3
27
+ requirement: &2157386460 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2157386460
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &2157423020 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.5.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2157423020
47
+ - !ruby/object:Gem::Dependency
48
+ name: generator_spec
49
+ requirement: &2157422520 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.2
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2157422520
58
+ description: The voter_love Gem allows users to easily vote on objects
59
+ email:
60
+ - karlgusner@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - MIT-LICENSE
69
+ - README.rdoc
70
+ - Rakefile
71
+ - lib/generators/voter_love/templates/migration.rb
72
+ - lib/generators/voter_love/voter_love_generator.rb
73
+ - lib/tasks/voter_love_tasks.rake
74
+ - lib/voter_love.rb
75
+ - lib/voter_love/exceptions.rb
76
+ - lib/voter_love/version.rb
77
+ - lib/voter_love/votable.rb
78
+ - lib/voter_love/voter.rb
79
+ - lib/voter_love/votes.rb
80
+ - spec/database.yml
81
+ - spec/database.yml.sample
82
+ - spec/generators/voter_love_generator_spec.rb
83
+ - spec/lib/voter_love_spec.rb
84
+ - spec/models.rb
85
+ - spec/schema.rb
86
+ - spec/spec_helper.rb
87
+ - voter_love.gemspec
88
+ homepage: https://github.com/ramz15/voter_love
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 1.8.11
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: An easy to use voting gem for Rails 3
112
+ test_files: []