voter_love 0.0.2

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/.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: []