acts_as_votable 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +0 -0
- data/Gemfile.lock +3 -2
- data/README.markdown +9 -24
- data/Rakefile +0 -0
- data/acts_as_votable.gemspec +1 -0
- data/lib/acts_as_votable.rb +4 -9
- data/lib/acts_as_votable/extenders/votable.rb +25 -0
- data/lib/acts_as_votable/extenders/voter.rb +24 -0
- data/lib/acts_as_votable/helpers/words.rb +36 -0
- data/lib/acts_as_votable/version.rb +1 -1
- data/lib/acts_as_votable/votable.rb +133 -99
- data/lib/acts_as_votable/vote.rb +4 -22
- data/lib/acts_as_votable/voter.rb +63 -53
- data/lib/generators/acts_as_votable/migration/migration_generator.rb +0 -0
- data/lib/generators/acts_as_votable/migration/templates/active_record/migration.rb +0 -0
- data/spec/spec_helper.rb +26 -1
- data/spec/votable_spec.rb +28 -3
- data/spec/voter_spec.rb +0 -0
- data/spec/words_spec.rb +30 -0
- metadata +52 -67
- data/lib/acts_as_votable/alias.rb +0 -14
- data/lib/acts_as_votable/init/init.rb +0 -5
- data/lib/acts_as_votable/init/votable.rb +0 -39
- data/lib/acts_as_votable/init/voter.rb +0 -30
- data/spec/alias_spec.rb +0 -64
- data/spec/vote_spec.rb +0 -34
data/.gitignore
CHANGED
data/Gemfile
CHANGED
File without changes
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
acts_as_votable (0.0
|
4
|
+
acts_as_votable (0.1.0)
|
5
5
|
rails (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -74,6 +74,7 @@ GEM
|
|
74
74
|
rspec-expectations (2.3.0)
|
75
75
|
diff-lcs (~> 1.1.2)
|
76
76
|
rspec-mocks (2.3.0)
|
77
|
+
sqlite3 (1.3.3)
|
77
78
|
thor (0.14.6)
|
78
79
|
treetop (1.4.9)
|
79
80
|
polyglot (>= 0.3.1)
|
@@ -84,5 +85,5 @@ PLATFORMS
|
|
84
85
|
|
85
86
|
DEPENDENCIES
|
86
87
|
acts_as_votable!
|
87
|
-
rails (>= 3.0.0)
|
88
88
|
rspec
|
89
|
+
sqlite3
|
data/README.markdown
CHANGED
@@ -1,16 +1,3 @@
|
|
1
|
-
### Major Updates
|
2
|
-
|
3
|
-
Version 0.1.0 introduces new and refactored function calls that improve the
|
4
|
-
natural language syntax of this gem. Certain calls that were compatible with
|
5
|
-
version 0.0.5 will now be broken. Remember to specify a the version in your
|
6
|
-
Gemfile to prevent functionality breakdowns between versions.
|
7
|
-
|
8
|
-
In version 0.1.0 functions like ``@post.votes`` return an array of all of the vote
|
9
|
-
records for @post. In order to count the number of votes simply use
|
10
|
-
``@post.votes.size`` now.
|
11
|
-
|
12
|
-
- - -
|
13
|
-
|
14
1
|
# Acts As Votable (aka Acts As Likeable)
|
15
2
|
|
16
3
|
Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models.
|
@@ -19,7 +6,7 @@ The main goals of this gem are:
|
|
19
6
|
- Allow any model to be voted on, like/dislike, upvote/downvote, etc.
|
20
7
|
- Allow any model to vote. In other words, votes do not have to come from a user,
|
21
8
|
they can come from any model (such as a Group or Team).
|
22
|
-
- Provide an easy to write
|
9
|
+
- Provide an easy to write/read syntax.
|
23
10
|
|
24
11
|
## Installation
|
25
12
|
|
@@ -110,7 +97,7 @@ You can have your voters ``acts_as_voter`` to provide some reserve functionality
|
|
110
97
|
|
111
98
|
@article.votes.size # => 1
|
112
99
|
@article.likes.size # => 1
|
113
|
-
@article.
|
100
|
+
@article.dislikes.size # => 0
|
114
101
|
|
115
102
|
To check if a voter has voted on a model, you can use ``voted_for?``. You can
|
116
103
|
check how the voter voted by using ``voted_as_when_voted_for``.
|
@@ -133,13 +120,13 @@ Voters can only vote once per model. In this example the 2nd vote does not coun
|
|
133
120
|
because @user has already voted for @shoe.
|
134
121
|
|
135
122
|
@user.likes @shoe
|
136
|
-
@user.
|
123
|
+
@user.likes @shoe
|
137
124
|
|
138
125
|
@shoe.votes # => 1
|
139
126
|
@shoe.likes # => 1
|
140
127
|
|
141
128
|
To check if a vote counted, or registered, use vote_registered? on your model
|
142
|
-
|
129
|
+
after voting. For example:
|
143
130
|
|
144
131
|
@hat.liked_by @user
|
145
132
|
@hat.vote_registered? # => true
|
@@ -181,20 +168,18 @@ to speed up @post we would use the following migration:
|
|
181
168
|
|
182
169
|
All tests follow the RSpec format and are located in the spec directory
|
183
170
|
|
184
|
-
## Thanks
|
185
|
-
|
186
|
-
A huge thank you to Michael Bleigh and his Acts-As-Taggable-On gem. I learned
|
187
|
-
how to write gems by following his source code.
|
188
|
-
|
189
171
|
## TODO
|
190
172
|
|
173
|
+
- Pass in a block of options when creating acts_as. Allow for things
|
174
|
+
like disabling the aliasing
|
175
|
+
|
191
176
|
- Smarter language syntax. Example: ``@user.likes`` will return all of the votables
|
192
177
|
that the user likes, while ``@user.likes @model`` will cast a vote for @model by
|
193
178
|
@user.
|
194
179
|
|
195
180
|
- Need to test a model that is votable as well as a voter
|
196
181
|
|
197
|
-
- The aliased
|
198
|
-
'true/false'. Need to come up with guidelines for naming these
|
182
|
+
- The aliased methods are referred to by using the terms 'up/down' and/or
|
183
|
+
'true/false'. Need to come up with guidelines for naming these methods.
|
199
184
|
|
200
185
|
- Create more aliases. Specifically for counting votes and finding votes.
|
data/Rakefile
CHANGED
File without changes
|
data/acts_as_votable.gemspec
CHANGED
data/lib/acts_as_votable.rb
CHANGED
@@ -3,19 +3,14 @@ require 'active_support/inflector'
|
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
5
|
|
6
|
-
require 'acts_as_votable/init/init'
|
7
|
-
require 'acts_as_votable/init/votable'
|
8
|
-
require 'acts_as_votable/init/voter'
|
9
|
-
require 'acts_as_votable/votable'
|
10
|
-
require 'acts_as_votable/voter'
|
11
|
-
require 'acts_as_votable/alias'
|
12
|
-
|
13
6
|
module ActsAsVotable
|
14
7
|
|
15
8
|
if defined?(ActiveRecord::Base)
|
9
|
+
require 'acts_as_votable/extenders/votable'
|
10
|
+
require 'acts_as_votable/extenders/voter'
|
16
11
|
require 'acts_as_votable/vote'
|
17
|
-
ActiveRecord::Base.extend ActsAsVotable::
|
18
|
-
ActiveRecord::Base.extend ActsAsVotable::
|
12
|
+
ActiveRecord::Base.extend ActsAsVotable::Extenders::Votable
|
13
|
+
ActiveRecord::Base.extend ActsAsVotable::Extenders::Voter
|
19
14
|
end
|
20
15
|
|
21
16
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActsAsVotable
|
2
|
+
module Extenders
|
3
|
+
|
4
|
+
module Votable
|
5
|
+
|
6
|
+
def votable?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def acts_as_votable
|
11
|
+
require 'acts_as_votable/votable'
|
12
|
+
include ActsAsVotable::Votable
|
13
|
+
|
14
|
+
class_eval do
|
15
|
+
def self.votable?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActsAsVotable
|
2
|
+
module Extenders
|
3
|
+
|
4
|
+
module Voter
|
5
|
+
|
6
|
+
def voter?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def acts_as_voter(*args)
|
11
|
+
require 'acts_as_votable/voter'
|
12
|
+
include ActsAsVotable::Voter
|
13
|
+
|
14
|
+
class_eval do
|
15
|
+
def self.voter?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActsAsVotable::Helpers
|
2
|
+
|
3
|
+
# this helper provides methods that help find what words are
|
4
|
+
# up votes and what words are down votes
|
5
|
+
#
|
6
|
+
# It can be called
|
7
|
+
#
|
8
|
+
# votable_object.votable_words.that_mean_true
|
9
|
+
#
|
10
|
+
module Words
|
11
|
+
|
12
|
+
def votable_words
|
13
|
+
VotableWords
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class VotableWords
|
19
|
+
|
20
|
+
def self.that_mean_true
|
21
|
+
['up', 'upvote', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.that_mean_false
|
25
|
+
['down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
|
26
|
+
end
|
27
|
+
|
28
|
+
# check is word is a true or bad vote
|
29
|
+
# if the word is unknown, then it counts it as a true/good
|
30
|
+
# vote. this exists to allow all voting to be good by default
|
31
|
+
def self.meaning_of word
|
32
|
+
!that_mean_false.include?(word)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -1,147 +1,181 @@
|
|
1
|
+
require 'acts_as_votable/helpers/words'
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
module Votable
|
3
5
|
|
4
|
-
|
5
|
-
base.send :include, ActsAsVotable::Votable::InstanceMethods
|
6
|
-
# base.extend ActsAsVotable::Votable::ClassMethods
|
7
|
-
end
|
6
|
+
include Helpers::Words
|
8
7
|
|
8
|
+
def self.included base
|
9
|
+
|
10
|
+
# allow the user to define these himself
|
11
|
+
aliases = {
|
9
12
|
|
10
|
-
|
11
|
-
|
13
|
+
:vote_up => [
|
14
|
+
:up_by, :upvote_by, :like_by, :liked_by, :vote_by,
|
15
|
+
:up_from, :upvote_from, :like_from, :liked_from, :vote_from
|
16
|
+
],
|
12
17
|
|
13
|
-
|
18
|
+
:vote_down => [
|
19
|
+
:down_by, :downvote_by, :dislike_by, :disliked_by,
|
20
|
+
:down_from, :downvote_by, :dislike_by, :disliked_by
|
21
|
+
],
|
14
22
|
|
15
|
-
|
23
|
+
:up_votes => [
|
24
|
+
:true_votes, :ups, :upvotes, :likes, :positives, :for_votes,
|
25
|
+
],
|
16
26
|
|
17
|
-
|
18
|
-
|
19
|
-
|
27
|
+
:down_votes => [
|
28
|
+
:false_votes, :downs, :downvotes, :dislikes, :negatives
|
29
|
+
]
|
20
30
|
|
21
|
-
|
22
|
-
{
|
23
|
-
:votable_id => self.id,
|
24
|
-
:votable_type => self.class.name
|
25
|
-
}
|
26
|
-
end
|
31
|
+
}
|
27
32
|
|
28
|
-
|
29
|
-
def vote args = {}
|
33
|
+
base.class_eval do
|
30
34
|
|
31
|
-
|
32
|
-
self.vote_registered = false
|
35
|
+
belongs_to :votable, :polymorphic => true
|
33
36
|
|
34
|
-
|
35
|
-
|
37
|
+
aliases.each do |method, links|
|
38
|
+
links.each do |new_method|
|
39
|
+
alias_method(new_method, method)
|
40
|
+
end
|
36
41
|
end
|
37
42
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
})
|
43
|
-
|
44
|
-
if votes.count == 0
|
45
|
-
# this voter has never voted
|
46
|
-
vote = ActsAsVotable::Vote.new(
|
47
|
-
:votable => self,
|
48
|
-
:voter => options[:voter]
|
49
|
-
)
|
50
|
-
else
|
51
|
-
# this voter is potentially changing his vote
|
52
|
-
vote = votes.first
|
53
|
-
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_accessor :vote_registered
|
54
47
|
|
55
|
-
|
48
|
+
def vote_registered?
|
49
|
+
return self.vote_registered
|
50
|
+
end
|
56
51
|
|
57
|
-
|
52
|
+
def default_conditions
|
53
|
+
{
|
54
|
+
:votable_id => self.id,
|
55
|
+
:votable_type => self.class.name
|
56
|
+
}
|
57
|
+
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
update_cached_votes
|
62
|
-
return true
|
63
|
-
else
|
64
|
-
self.vote_registered = false
|
65
|
-
return false
|
66
|
-
end
|
59
|
+
# voting
|
60
|
+
def vote args = {}
|
67
61
|
|
68
|
-
|
69
|
-
|
62
|
+
options = {
|
63
|
+
:vote => true,
|
64
|
+
}.merge(args)
|
65
|
+
|
66
|
+
self.vote_registered = false
|
70
67
|
|
71
|
-
|
72
|
-
|
68
|
+
if options[:voter].nil?
|
69
|
+
return false
|
73
70
|
end
|
74
71
|
|
75
|
-
|
76
|
-
|
72
|
+
# find the vote
|
73
|
+
votes = find_votes({
|
74
|
+
:voter_id => options[:voter].id,
|
75
|
+
:voter_type => options[:voter].class.name
|
76
|
+
})
|
77
|
+
|
78
|
+
if votes.count == 0
|
79
|
+
# this voter has never voted
|
80
|
+
vote = ActsAsVotable::Vote.new(
|
81
|
+
:votable => self,
|
82
|
+
:voter => options[:voter]
|
83
|
+
)
|
84
|
+
# redefine type if this object has a type. this is to deal
|
85
|
+
# with sti classes
|
86
|
+
vote.votable_type = type if respond_to?(:type) && !type.blank?
|
87
|
+
else
|
88
|
+
# this voter is potentially changing his vote
|
89
|
+
vote = votes.first
|
77
90
|
end
|
78
91
|
|
79
|
-
|
80
|
-
def update_cached_votes
|
92
|
+
last_update = vote.updated_at
|
81
93
|
|
82
|
-
|
94
|
+
vote.vote_flag = votable_words.meaning_of(options[:vote])
|
83
95
|
|
84
|
-
|
85
|
-
|
86
|
-
|
96
|
+
if vote.save
|
97
|
+
self.vote_registered = true if last_update != vote.updated_at
|
98
|
+
update_cached_votes
|
99
|
+
return true
|
100
|
+
else
|
101
|
+
self.vote_registered = false
|
102
|
+
return false
|
103
|
+
end
|
87
104
|
|
88
|
-
|
89
|
-
updates[:cached_votes_up] = count_votes_up(true)
|
90
|
-
end
|
105
|
+
end
|
91
106
|
|
92
|
-
|
93
|
-
|
94
|
-
|
107
|
+
def vote_up voter
|
108
|
+
self.vote :voter => voter, :vote => true
|
109
|
+
end
|
95
110
|
|
96
|
-
|
111
|
+
def vote_down voter
|
112
|
+
self.vote :voter => voter, :vote => false
|
113
|
+
end
|
97
114
|
|
98
|
-
|
115
|
+
# caching
|
116
|
+
def update_cached_votes
|
99
117
|
|
118
|
+
updates = {}
|
100
119
|
|
101
|
-
|
102
|
-
|
103
|
-
ActsAsVotable::Vote.find(:all, :conditions => default_conditions.merge(extra_conditions))
|
120
|
+
if self.respond_to?(:cached_votes_total=)
|
121
|
+
updates[:cached_votes_total] = count_votes_total(true)
|
104
122
|
end
|
105
|
-
alias :votes :find_votes
|
106
123
|
|
107
|
-
|
108
|
-
|
124
|
+
if self.respond_to?(:cached_votes_up=)
|
125
|
+
updates[:cached_votes_up] = count_votes_up(true)
|
109
126
|
end
|
110
127
|
|
111
|
-
|
112
|
-
|
128
|
+
if self.respond_to?(:cached_votes_down=)
|
129
|
+
updates[:cached_votes_down] = count_votes_down(true)
|
113
130
|
end
|
114
131
|
|
132
|
+
self.update_attributes(updates) if updates.size > 0
|
115
133
|
|
116
|
-
|
117
|
-
def count_votes_total skip_cache = false
|
118
|
-
if !skip_cache && self.respond_to?(:cached_votes_total)
|
119
|
-
return self.send(:cached_votes_total)
|
120
|
-
end
|
121
|
-
find_votes.size
|
122
|
-
end
|
134
|
+
end
|
123
135
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
136
|
+
|
137
|
+
# results
|
138
|
+
def find_votes extra_conditions = {}
|
139
|
+
ActsAsVotable::Vote.find(:all, :conditions => default_conditions.merge(extra_conditions))
|
140
|
+
end
|
141
|
+
alias :votes :find_votes
|
142
|
+
|
143
|
+
def up_votes
|
144
|
+
find_votes(:vote_flag => true)
|
145
|
+
end
|
146
|
+
|
147
|
+
def down_votes
|
148
|
+
find_votes(:vote_flag => false)
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
# counting
|
153
|
+
def count_votes_total skip_cache = false
|
154
|
+
if !skip_cache && self.respond_to?(:cached_votes_total)
|
155
|
+
return self.send(:cached_votes_total)
|
129
156
|
end
|
157
|
+
find_votes.size
|
158
|
+
end
|
130
159
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
down_votes.size
|
160
|
+
def count_votes_up skip_cache = false
|
161
|
+
if !skip_cache && self.respond_to?(:cached_votes_up)
|
162
|
+
return self.send(:cached_votes_up)
|
136
163
|
end
|
164
|
+
up_votes.size
|
165
|
+
end
|
137
166
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
votes.size > 0
|
167
|
+
def count_votes_down skip_cache = false
|
168
|
+
if !skip_cache && self.respond_to?(:cached_votes_down)
|
169
|
+
return self.send(:cached_votes_down)
|
142
170
|
end
|
171
|
+
down_votes.size
|
172
|
+
end
|
143
173
|
|
174
|
+
# voters
|
175
|
+
def voted_on_by? voter
|
176
|
+
votes = find_votes :voter_id => voter.id, :voter_type => voter.class.name
|
177
|
+
votes.size > 0
|
144
178
|
end
|
145
179
|
|
146
180
|
end
|
147
|
-
end
|
181
|
+
end
|
data/lib/acts_as_votable/vote.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'acts_as_votable/helpers/words'
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
class Vote < ::ActiveRecord::Base
|
3
5
|
|
6
|
+
include Helpers::Words
|
7
|
+
|
4
8
|
attr_accessible :votable_id, :votable_type,
|
5
9
|
:voter_id, :voter_type,
|
6
10
|
:votable, :voter,
|
@@ -12,28 +16,6 @@ module ActsAsVotable
|
|
12
16
|
validates_presence_of :votable_id
|
13
17
|
validates_presence_of :voter_id
|
14
18
|
|
15
|
-
def self.true_votes
|
16
|
-
['up', 'upvote', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.false_votes
|
20
|
-
['down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
|
21
|
-
end
|
22
|
-
|
23
|
-
##
|
24
|
-
# check is word is a true or bad vote
|
25
|
-
# if the word is unknown, then it counts it as a true/good
|
26
|
-
# vote. this exists to allow all voting to be good by default
|
27
|
-
def self.word_is_a_vote_for word
|
28
|
-
!false_votes.include? word
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.default_voting_args
|
32
|
-
{
|
33
|
-
:vote => true,
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
19
|
end
|
38
20
|
|
39
21
|
end
|
@@ -2,76 +2,86 @@ module ActsAsVotable
|
|
2
2
|
module Voter
|
3
3
|
|
4
4
|
def self.included(base)
|
5
|
-
base.send :include, ActsAsVotable::Voter::InstanceMethods
|
6
|
-
end
|
7
5
|
|
6
|
+
# allow user to define these
|
7
|
+
aliases = {
|
8
|
+
:vote_up_for => [:likes, :upvotes, :up_votes],
|
9
|
+
:vote_down_for => [:dislikes, :downvotes, :down_votes]
|
10
|
+
}
|
8
11
|
|
9
|
-
|
10
|
-
end
|
12
|
+
base.class_eval do
|
11
13
|
|
12
|
-
|
14
|
+
belongs_to :voter, :polymorphic => true
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
16
|
+
aliases.each do |method, links|
|
17
|
+
links.each do |new_method|
|
18
|
+
alias_method(new_method, method)
|
19
|
+
end
|
20
|
+
end
|
20
21
|
|
21
|
-
# voting
|
22
|
-
def vote args
|
23
|
-
args[:votable].vote args.merge({:voter => self})
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
|
-
vote :votable => model, :vote => true
|
28
|
-
end
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
def default_conditions
|
27
|
+
{
|
28
|
+
:voter_id => self.id,
|
29
|
+
:voter_type => self.class.name
|
30
|
+
}
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
alias :voted_for? :voted_on?
|
33
|
+
# voting
|
34
|
+
def vote args
|
35
|
+
args[:votable].vote args.merge({:voter => self})
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
return votes.first.vote_flag
|
45
|
-
end
|
46
|
-
alias :voted_as_when_voting_for :voted_as_when_voting_on
|
38
|
+
def vote_up_for model
|
39
|
+
vote :votable => model, :vote => true
|
40
|
+
end
|
47
41
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
alias :votes :find_votes
|
42
|
+
def vote_down_for model
|
43
|
+
vote :votable => model, :vote => false
|
44
|
+
end
|
53
45
|
|
54
|
-
|
55
|
-
|
56
|
-
|
46
|
+
# results
|
47
|
+
def voted_on? votable
|
48
|
+
votes = find_votes(:votable_id => votable.id, :votable_type => votable.class.name)
|
49
|
+
votes.size > 0
|
50
|
+
end
|
51
|
+
alias :voted_for? :voted_on?
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
def voted_as_when_voting_on votable
|
54
|
+
votes = find_votes(:votable_id => votable.id, :votable_type => votable.class.name)
|
55
|
+
return nil if votes.size == 0
|
56
|
+
return votes.first.vote_flag
|
57
|
+
end
|
58
|
+
alias :voted_as_when_voting_for :voted_as_when_voting_on
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
def find_votes extra_conditions = {}
|
61
|
+
ActsAsVotable::Vote.find(:all, :conditions => default_conditions.merge(extra_conditions))
|
62
|
+
end
|
63
|
+
alias :votes :find_votes
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
def find_up_votes
|
66
|
+
find_votes :vote_flag => true
|
67
|
+
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
def find_down_votes
|
70
|
+
find_votes :vote_flag => false
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_votes_for_class klass, extra_conditions = {}
|
74
|
+
find_votes extra_conditions.merge({:votable_type => klass.name})
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_up_votes_for_class klass
|
78
|
+
find_votes_for_class klass, :vote_flag => true
|
79
|
+
end
|
73
80
|
|
81
|
+
def find_down_votes_for_class klass
|
82
|
+
find_votes_for_class klass, :vote_flag => false
|
74
83
|
end
|
75
84
|
|
85
|
+
|
76
86
|
end
|
77
|
-
end
|
87
|
+
end
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -28,6 +28,16 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
28
28
|
t.string :name
|
29
29
|
end
|
30
30
|
|
31
|
+
create_table :sti_votables do |t|
|
32
|
+
t.string :name
|
33
|
+
t.string :type
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :sti_not_votables do |t|
|
37
|
+
t.string :name
|
38
|
+
t.string :type
|
39
|
+
end
|
40
|
+
|
31
41
|
create_table :not_votables do |t|
|
32
42
|
t.string :name
|
33
43
|
end
|
@@ -55,6 +65,21 @@ class Votable < ActiveRecord::Base
|
|
55
65
|
validates_presence_of :name
|
56
66
|
end
|
57
67
|
|
68
|
+
class StiVotable < ActiveRecord::Base
|
69
|
+
acts_as_votable
|
70
|
+
end
|
71
|
+
|
72
|
+
class ChildOfStiVotable < StiVotable
|
73
|
+
end
|
74
|
+
|
75
|
+
class StiNotVotable < ActiveRecord::Base
|
76
|
+
validates_presence_of :name
|
77
|
+
end
|
78
|
+
|
79
|
+
class VotableChildOfStiNotVotable < StiNotVotable
|
80
|
+
acts_as_votable
|
81
|
+
end
|
82
|
+
|
58
83
|
class NotVotable < ActiveRecord::Base
|
59
84
|
end
|
60
85
|
|
@@ -75,4 +100,4 @@ def clean_database
|
|
75
100
|
models.each do |model|
|
76
101
|
ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
|
77
102
|
end
|
78
|
-
end
|
103
|
+
end
|
data/spec/votable_spec.rb
CHANGED
@@ -111,8 +111,6 @@ describe ActsAsVotable::Votable do
|
|
111
111
|
votable2.vote_registered?.should be false
|
112
112
|
end
|
113
113
|
|
114
|
-
|
115
|
-
|
116
114
|
describe "with cached votes" do
|
117
115
|
|
118
116
|
before(:each) do
|
@@ -170,7 +168,34 @@ describe ActsAsVotable::Votable do
|
|
170
168
|
|
171
169
|
end
|
172
170
|
|
171
|
+
describe "sti models" do
|
172
|
+
|
173
|
+
before(:each) do
|
174
|
+
clean_database
|
175
|
+
@voter = Voter.create(:name => 'i can vote!')
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should be able to vote on a votable child of a non votable sti model" do
|
179
|
+
votable = VotableChildOfStiNotVotable.create(:name => 'sti child')
|
180
|
+
|
181
|
+
votable.vote :voter => @voter, :vote => 'yes'
|
182
|
+
votable.votes.size.should == 1
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should not be able to vote on a parent non votable" do
|
186
|
+
StiNotVotable.should_not be_votable
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should be able to vote on a child when its parent is votable" do
|
190
|
+
votable = ChildOfStiVotable.create(:name => 'sti child')
|
191
|
+
|
192
|
+
votable.vote :voter => @voter, :vote => 'yes'
|
193
|
+
votable.votes.size.should == 1
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
173
198
|
end
|
174
199
|
|
175
200
|
|
176
|
-
end
|
201
|
+
end
|
data/spec/voter_spec.rb
CHANGED
File without changes
|
data/spec/words_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'acts_as_votable'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActsAsVotable::Helpers::Words do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@vote = ActsAsVotable::Vote.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should know that like is a true vote" do
|
11
|
+
@vote.votable_words.that_mean_true.should include "like"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should know that bad is a false vote" do
|
15
|
+
@vote.votable_words.that_mean_false.should include "bad"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be a vote for true when word is good" do
|
19
|
+
@vote.votable_words.meaning_of('good').should be true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be a vote for false when word is down" do
|
23
|
+
@vote.votable_words.meaning_of('down').should be false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be a vote for true when the word is unknown" do
|
27
|
+
@vote.votable_words.meaning_of('lsdhklkadhfs').should be true
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
CHANGED
@@ -1,60 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_votable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: 0.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Ryan
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-10-08 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: rspec
|
16
|
+
requirement: &2950990 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
22
23
|
prerelease: false
|
23
|
-
|
24
|
+
version_requirements: *2950990
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sqlite3
|
27
|
+
requirement: &2950780 !ruby/object:Gem::Requirement
|
24
28
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 0
|
30
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
31
33
|
type: :development
|
32
|
-
version_requirements: *id001
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: rails
|
35
34
|
prerelease: false
|
36
|
-
|
35
|
+
version_requirements: *2950780
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rails
|
38
|
+
requirement: &2950530 !ruby/object:Gem::Requirement
|
37
39
|
none: false
|
38
|
-
requirements:
|
39
|
-
- -
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
segments:
|
42
|
-
- 3
|
43
|
-
- 0
|
44
|
-
- 0
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
45
43
|
version: 3.0.0
|
46
44
|
type: :runtime
|
47
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2950530
|
48
47
|
description: Rails gem to allowing records to be votable
|
49
|
-
email:
|
48
|
+
email:
|
50
49
|
- ryanto
|
51
50
|
executables: []
|
52
|
-
|
53
51
|
extensions: []
|
54
|
-
|
55
52
|
extra_rdoc_files: []
|
56
|
-
|
57
|
-
files:
|
53
|
+
files:
|
58
54
|
- .gitignore
|
59
55
|
- Gemfile
|
60
56
|
- Gemfile.lock
|
@@ -62,56 +58,45 @@ files:
|
|
62
58
|
- Rakefile
|
63
59
|
- acts_as_votable.gemspec
|
64
60
|
- lib/acts_as_votable.rb
|
65
|
-
- lib/acts_as_votable/
|
66
|
-
- lib/acts_as_votable/
|
67
|
-
- lib/acts_as_votable/
|
68
|
-
- lib/acts_as_votable/init/voter.rb
|
61
|
+
- lib/acts_as_votable/extenders/votable.rb
|
62
|
+
- lib/acts_as_votable/extenders/voter.rb
|
63
|
+
- lib/acts_as_votable/helpers/words.rb
|
69
64
|
- lib/acts_as_votable/version.rb
|
70
65
|
- lib/acts_as_votable/votable.rb
|
71
66
|
- lib/acts_as_votable/vote.rb
|
72
67
|
- lib/acts_as_votable/voter.rb
|
73
68
|
- lib/generators/acts_as_votable/migration/migration_generator.rb
|
74
69
|
- lib/generators/acts_as_votable/migration/templates/active_record/migration.rb
|
75
|
-
- spec/alias_spec.rb
|
76
70
|
- spec/spec_helper.rb
|
77
71
|
- spec/votable_spec.rb
|
78
|
-
- spec/vote_spec.rb
|
79
72
|
- spec/voter_spec.rb
|
80
|
-
|
73
|
+
- spec/words_spec.rb
|
81
74
|
homepage: http://rubygems.org/gems/acts_as_votable
|
82
75
|
licenses: []
|
83
|
-
|
84
76
|
post_install_message:
|
85
77
|
rdoc_options: []
|
86
|
-
|
87
|
-
require_paths:
|
78
|
+
require_paths:
|
88
79
|
- lib
|
89
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
81
|
none: false
|
91
|
-
requirements:
|
92
|
-
- -
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
|
95
|
-
|
96
|
-
version: "0"
|
97
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
87
|
none: false
|
99
|
-
requirements:
|
100
|
-
- -
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
|
103
|
-
- 0
|
104
|
-
version: "0"
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
105
92
|
requirements: []
|
106
|
-
|
107
93
|
rubyforge_project: acts_as_votable
|
108
|
-
rubygems_version: 1.
|
94
|
+
rubygems_version: 1.8.11
|
109
95
|
signing_key:
|
110
96
|
specification_version: 3
|
111
97
|
summary: Rails gem to allowing records to be votable
|
112
|
-
test_files:
|
113
|
-
- spec/alias_spec.rb
|
98
|
+
test_files:
|
114
99
|
- spec/spec_helper.rb
|
115
100
|
- spec/votable_spec.rb
|
116
|
-
- spec/vote_spec.rb
|
117
101
|
- spec/voter_spec.rb
|
102
|
+
- spec/words_spec.rb
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module ActsAsVotable::Alias
|
2
|
-
|
3
|
-
def self.words_to_alias object, words, call_function
|
4
|
-
words.each do |word|
|
5
|
-
if word.is_a?(String)
|
6
|
-
function = word.to_sym
|
7
|
-
if !object.respond_to?(function)
|
8
|
-
object.send(:alias_method, function, call_function)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module ActsAsVotable::Init
|
2
|
-
|
3
|
-
module Votable
|
4
|
-
|
5
|
-
def votable?
|
6
|
-
false
|
7
|
-
end
|
8
|
-
|
9
|
-
def acts_as_votable(*args)
|
10
|
-
|
11
|
-
class_eval do
|
12
|
-
belongs_to :votable, :polymorphic => true
|
13
|
-
|
14
|
-
def self.votable?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
include ActsAsVotable::Votable
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
# aliasing
|
23
|
-
|
24
|
-
# voting
|
25
|
-
ActsAsVotable::Alias::words_to_alias self, %w(up_by upvote_by like_by liked_by vote_by), :vote_up
|
26
|
-
ActsAsVotable::Alias::words_to_alias self, %w(up_from upvote_from like_from liked_from vote_from), :vote_up
|
27
|
-
ActsAsVotable::Alias::words_to_alias self, %w(down_by downvote_by dislike_by disliked_by), :vote_down
|
28
|
-
ActsAsVotable::Alias::words_to_alias self, %w(down_from downvote_from dislike_from disliked_from), :vote_down
|
29
|
-
|
30
|
-
# finding
|
31
|
-
ActsAsVotable::Alias::words_to_alias self, %w(true_votes ups upvotes likes positives), :up_votes
|
32
|
-
ActsAsVotable::Alias::words_to_alias self, %w(false_votes downs downvotes dislikes negatives), :down_votes
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module ActsAsVotable::Init
|
2
|
-
|
3
|
-
# voter
|
4
|
-
module Voter
|
5
|
-
|
6
|
-
def voter?
|
7
|
-
false
|
8
|
-
end
|
9
|
-
|
10
|
-
def acts_as_voter(*args)
|
11
|
-
|
12
|
-
class_eval do
|
13
|
-
belongs_to :voter, :polymorphic => true
|
14
|
-
|
15
|
-
def self.voter?
|
16
|
-
true
|
17
|
-
end
|
18
|
-
|
19
|
-
include ActsAsVotable::Voter
|
20
|
-
|
21
|
-
ActsAsVotable::Alias::words_to_alias self, %w(likes upvotes up_votes), :vote_up_for
|
22
|
-
ActsAsVotable::Alias::words_to_alias self, %w(dislikes downvotes down_votes), :vote_down_for
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
data/spec/alias_spec.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'acts_as_votable'
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe ActsAsVotable::Alias do
|
5
|
-
|
6
|
-
before(:each) do
|
7
|
-
clean_database
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "votable models" do
|
11
|
-
|
12
|
-
before(:each) do
|
13
|
-
clean_database
|
14
|
-
@votable = Votable.new(:name => 'votable with aliases')
|
15
|
-
@votable.save
|
16
|
-
|
17
|
-
@voter = Voter.new(:name => 'a voter')
|
18
|
-
@voter.save
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should alias a bunch of functions" do
|
22
|
-
|
23
|
-
# voting
|
24
|
-
@votable.respond_to?(:disliked_by).should be true
|
25
|
-
@votable.respond_to?(:up_from).should be true
|
26
|
-
|
27
|
-
# results
|
28
|
-
@votable.respond_to?(:upvotes).should be true
|
29
|
-
@votable.respond_to?(:ups).should be true
|
30
|
-
@votable.respond_to?(:dislikes).should be true
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should add callable functions" do
|
35
|
-
@votable.vote :voter => @voter
|
36
|
-
@votable.likes.size.should == 1
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "voter models" do
|
41
|
-
|
42
|
-
before(:each) do
|
43
|
-
clean_database
|
44
|
-
@votable = Votable.new(:name => 'a votable')
|
45
|
-
@votable.save
|
46
|
-
|
47
|
-
@voter = Voter.new(:name => 'a voter with aliases')
|
48
|
-
@voter.save
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should alias a bunch of functions" do
|
52
|
-
@voter.respond_to?(:upvotes).should be true
|
53
|
-
@voter.respond_to?(:dislikes).should be true
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should add callable functions" do
|
57
|
-
@voter.likes @votable
|
58
|
-
@votable.likes.size.should == 1
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
data/spec/vote_spec.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'acts_as_votable'
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe ActsAsVotable::Vote do
|
5
|
-
|
6
|
-
it "should know that like is a true vote" do
|
7
|
-
ActsAsVotable::Vote.true_votes.should include "like"
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should know that bad is a false vote" do
|
11
|
-
ActsAsVotable::Vote.false_votes.should include "bad"
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should be a vote for true when word is good" do
|
15
|
-
ActsAsVotable::Vote.word_is_a_vote_for('good').should be true
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should be a vote for false when word is down" do
|
19
|
-
ActsAsVotable::Vote.word_is_a_vote_for('down').should be false
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should be a vote for true when the word is unknown" do
|
23
|
-
ActsAsVotable::Vote.word_is_a_vote_for('lsdhklkadhfs').should be true
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should have vote=>true in the default voting args" do
|
27
|
-
ActsAsVotable::Vote.default_voting_args[:vote].should be true
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|