voteable_mongoid 0.6.4 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -6
- data/README.rdoc +2 -3
- data/lib/voteable_mongoid/version.rb +1 -1
- data/lib/voteable_mongoid/voteable.rb +52 -52
- data/lib/voteable_mongoid/voteable/stats.rb +24 -24
- data/lib/voteable_mongoid/voteable/votes.rb +30 -32
- metadata +4 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
+
== 0.7.0
|
2
|
+
* Use readable field names (up, down, up_count, down_count, count, point) instead of very short field names (u, d, uc, dc, c, p)
|
3
|
+
|
1
4
|
== 0.6.4
|
2
5
|
* Drop Voter#votees, Voter#up_votees, Voter#down_votees in favor of Voteable#voted_by(voter), Voteable#up_voted_by(voter), Voteable#down_voted_by(voter) scopes
|
3
|
-
|
6
|
+
|
4
7
|
== 0.6.3
|
5
8
|
* Add rake db:mongoid:voteable:migrate_old_votes to migrate vote data created by version < 0.6.0 to new vote data storage
|
6
9
|
|
7
10
|
== 0.6.2
|
8
11
|
* Fix bug: use before_create instead of after_after_initialize
|
9
|
-
|
12
|
+
|
10
13
|
== 0.6.1
|
11
14
|
* Set counters and point to 0 for uninitialized voteable objects in order sort and query
|
12
|
-
|
15
|
+
|
13
16
|
== 0.6.0
|
14
17
|
* Minimize vote data store (using short field names votes.u, votes.d, votes.c ...)
|
15
18
|
* Add Voter#up_votees, Voter#down_votees
|
@@ -18,15 +21,15 @@
|
|
18
21
|
|
19
22
|
== 0.5.0
|
20
23
|
* Rename vote_point to voteable
|
21
|
-
|
24
|
+
|
22
25
|
== 0.4.5
|
23
26
|
* Can use rake db:mongoid:voteable:remake_stats in Rails apps
|
24
27
|
* Use mongoid 2.0.0
|
25
|
-
|
28
|
+
|
26
29
|
== 0.4.4
|
27
30
|
* Add up_votes_count, down_votes_count
|
28
31
|
* Re-generate vote statistic data (counters and point)
|
29
|
-
|
32
|
+
|
30
33
|
== 0.4.3
|
31
34
|
* Wrap vote data in voteable namespace (voteable.up_voters_id, voteable.down_voters_ids, voteable.votes_count ...)
|
32
35
|
|
data/README.rdoc
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
Voteable Mongoid allows you to make your Mongoid::Document objects voteable (up or down).
|
4
4
|
For instance, in a forum, a user can vote up (or down) on a post or a comment.
|
5
5
|
|
6
|
-
Voteable Mongoid is built for speed. It
|
7
|
-
only one database request per collection to do both data validation and data update.
|
6
|
+
Voteable Mongoid is built for speed. It uses only one database request per collection to do both data validation and data update.
|
8
7
|
|
9
8
|
Sample app at https://github.com/vinova/simple_qa
|
10
9
|
|
@@ -97,7 +96,7 @@ Rails
|
|
97
96
|
Ruby
|
98
97
|
Mongoid::Voteable::Stats.init
|
99
98
|
|
100
|
-
=== Migrate from version < 0.
|
99
|
+
=== Migrate from version < 0.7.0
|
101
100
|
Rails
|
102
101
|
rake db:mongoid:voteable:migrate_old_votes
|
103
102
|
Ruby
|
@@ -13,17 +13,17 @@ module Mongoid
|
|
13
13
|
|
14
14
|
scope :voted_by, lambda { |voter|
|
15
15
|
voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter._id
|
16
|
-
any_of({
|
16
|
+
any_of({ 'votes.up' => voter_id }, { 'votes.down' => voter_id })
|
17
17
|
}
|
18
18
|
|
19
19
|
scope :up_voted_by, lambda { |voter|
|
20
20
|
voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter._id
|
21
|
-
where(
|
21
|
+
where( 'votes.up' => voter_id )
|
22
22
|
}
|
23
23
|
|
24
24
|
scope :down_voted_by, lambda { |voter|
|
25
25
|
voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter._id
|
26
|
-
where(
|
26
|
+
where( 'votes.down' => voter_id )
|
27
27
|
}
|
28
28
|
|
29
29
|
before_create do
|
@@ -67,21 +67,21 @@ module Mongoid
|
|
67
67
|
|
68
68
|
klass = options[:class]
|
69
69
|
klass ||= VOTEABLE.keys.include?(name) ? name : collection.name.classify
|
70
|
-
|
70
|
+
voteable = VOTEABLE[klass][klass]
|
71
71
|
|
72
72
|
if options[:revote]
|
73
73
|
if value == :up
|
74
|
-
positive_voter_ids =
|
75
|
-
negative_voter_ids =
|
76
|
-
positive_votes_count =
|
77
|
-
negative_votes_count =
|
78
|
-
point_delta =
|
74
|
+
positive_voter_ids = 'votes.up'
|
75
|
+
negative_voter_ids = 'votes.down'
|
76
|
+
positive_votes_count = 'votes.up_count'
|
77
|
+
negative_votes_count = 'votes.down_count'
|
78
|
+
point_delta = voteable[:up] - voteable[:down]
|
79
79
|
else
|
80
|
-
positive_voter_ids =
|
81
|
-
negative_voter_ids =
|
82
|
-
positive_votes_count =
|
83
|
-
negative_votes_count =
|
84
|
-
point_delta = -
|
80
|
+
positive_voter_ids = 'votes.down'
|
81
|
+
negative_voter_ids = 'votes.up'
|
82
|
+
positive_votes_count = 'votes.down_count'
|
83
|
+
negative_votes_count = 'votes.up_count'
|
84
|
+
point_delta = -voteable[:up] + voteable[:down]
|
85
85
|
end
|
86
86
|
|
87
87
|
update_result = collection.update({
|
@@ -96,7 +96,7 @@ module Mongoid
|
|
96
96
|
'$inc' => {
|
97
97
|
positive_votes_count => +1,
|
98
98
|
negative_votes_count => -1,
|
99
|
-
|
99
|
+
'votes.point' => point_delta
|
100
100
|
}
|
101
101
|
}, {
|
102
102
|
:safe => true
|
@@ -104,13 +104,13 @@ module Mongoid
|
|
104
104
|
|
105
105
|
elsif options[:unvote]
|
106
106
|
if value == :up
|
107
|
-
positive_voter_ids =
|
108
|
-
negative_voter_ids =
|
109
|
-
positive_votes_count =
|
107
|
+
positive_voter_ids = 'votes.up'
|
108
|
+
negative_voter_ids = 'votes.down'
|
109
|
+
positive_votes_count = 'votes.up_count'
|
110
110
|
else
|
111
|
-
positive_voter_ids =
|
112
|
-
negative_voter_ids =
|
113
|
-
positive_votes_count =
|
111
|
+
positive_voter_ids = 'votes.down'
|
112
|
+
negative_voter_ids = 'votes.up'
|
113
|
+
positive_votes_count = 'votes.down_count'
|
114
114
|
end
|
115
115
|
|
116
116
|
# Check if voter_id did a vote with value for votee_id
|
@@ -124,8 +124,8 @@ module Mongoid
|
|
124
124
|
'$pull' => { positive_voter_ids => voter_id },
|
125
125
|
'$inc' => {
|
126
126
|
positive_votes_count => -1,
|
127
|
-
|
128
|
-
|
127
|
+
'votes.count' => -1,
|
128
|
+
'votes.point' => -voteable[value]
|
129
129
|
}
|
130
130
|
}, {
|
131
131
|
:safe => true
|
@@ -133,25 +133,25 @@ module Mongoid
|
|
133
133
|
|
134
134
|
else # new vote
|
135
135
|
if value.to_sym == :up
|
136
|
-
positive_voter_ids =
|
137
|
-
positive_votes_count =
|
136
|
+
positive_voter_ids = 'votes.up'
|
137
|
+
positive_votes_count = 'votes.up_count'
|
138
138
|
else
|
139
|
-
positive_voter_ids =
|
140
|
-
positive_votes_count =
|
139
|
+
positive_voter_ids = 'votes.down'
|
140
|
+
positive_votes_count = 'votes.down_count'
|
141
141
|
end
|
142
142
|
|
143
143
|
update_result = collection.update({
|
144
144
|
# Validate voter_id did not vote for votee_id yet
|
145
145
|
:_id => votee_id,
|
146
|
-
|
147
|
-
|
146
|
+
'votes.up' => { '$ne' => voter_id },
|
147
|
+
'votes.down' => { '$ne' => voter_id }
|
148
148
|
}, {
|
149
149
|
# then update
|
150
150
|
'$push' => { positive_voter_ids => voter_id },
|
151
151
|
'$inc' => {
|
152
|
-
|
152
|
+
'votes.count' => +1,
|
153
153
|
positive_votes_count => +1,
|
154
|
-
|
154
|
+
'votes.point' => voteable[value] }
|
155
155
|
}, {
|
156
156
|
:safe => true
|
157
157
|
})
|
@@ -163,7 +163,7 @@ module Mongoid
|
|
163
163
|
update_result['n'] == 1 )
|
164
164
|
|
165
165
|
if successed
|
166
|
-
VOTEABLE[klass].each do |class_name,
|
166
|
+
VOTEABLE[klass].each do |class_name, voteable|
|
167
167
|
# For other class in VOTEABLE options, if is parent of current class
|
168
168
|
next unless relation_metadata = relations[class_name.underscore]
|
169
169
|
next unless votee ||= options[:votee] || find(options[:votee_id])
|
@@ -174,36 +174,36 @@ module Mongoid
|
|
174
174
|
|
175
175
|
if options[:revote]
|
176
176
|
if value == :up
|
177
|
-
inc_options[
|
178
|
-
unless
|
179
|
-
inc_options[
|
180
|
-
inc_options[
|
177
|
+
inc_options['votes.point'] = voteable[:up] - voteable[:down]
|
178
|
+
unless voteable[:update_counters] == false
|
179
|
+
inc_options['votes.up_count'] = +1
|
180
|
+
inc_options['votes.down_count'] = -1
|
181
181
|
end
|
182
182
|
else
|
183
|
-
inc_options[
|
184
|
-
unless
|
185
|
-
inc_options[
|
186
|
-
inc_options[
|
183
|
+
inc_options['votes.point'] = -voteable[:up] + voteable[:down]
|
184
|
+
unless voteable[:update_counters] == false
|
185
|
+
inc_options['votes.up_count'] = -1
|
186
|
+
inc_options['votes.down_count'] = +1
|
187
187
|
end
|
188
188
|
end
|
189
189
|
elsif options[:unvote]
|
190
|
-
inc_options[
|
191
|
-
unless
|
192
|
-
inc_options[
|
190
|
+
inc_options['votes.point'] = -voteable[value]
|
191
|
+
unless voteable[:update_counters] == false
|
192
|
+
inc_options['votes.count'] = -1
|
193
193
|
if value == :up
|
194
|
-
inc_options[
|
194
|
+
inc_options['votes.up_count'] = -1
|
195
195
|
else
|
196
|
-
inc_options[
|
196
|
+
inc_options['votes.down_count'] = -1
|
197
197
|
end
|
198
198
|
end
|
199
199
|
else # new vote
|
200
|
-
inc_options[
|
201
|
-
unless
|
202
|
-
inc_options[
|
200
|
+
inc_options['votes.point'] = voteable[value]
|
201
|
+
unless voteable[:update_counters] == false
|
202
|
+
inc_options['votes.count'] = +1
|
203
203
|
if value == :up
|
204
|
-
inc_options[
|
204
|
+
inc_options['votes.up_count'] = +1
|
205
205
|
else
|
206
|
-
inc_options[
|
206
|
+
inc_options['votes.down_count'] = +1
|
207
207
|
end
|
208
208
|
end
|
209
209
|
end
|
@@ -247,12 +247,12 @@ module Mongoid
|
|
247
247
|
|
248
248
|
# Array of up voter ids
|
249
249
|
def up_voter_ids
|
250
|
-
votes.try(:[], '
|
250
|
+
votes.try(:[], 'up') || []
|
251
251
|
end
|
252
252
|
|
253
253
|
# Array of down voter ids
|
254
254
|
def down_voter_ids
|
255
|
-
votes.try(:[], '
|
255
|
+
votes.try(:[], 'down') || []
|
256
256
|
end
|
257
257
|
end
|
258
258
|
end
|
@@ -5,28 +5,28 @@ module Mongoid
|
|
5
5
|
|
6
6
|
# Get the number of up votes
|
7
7
|
def up_votes_count
|
8
|
-
votes.try(:[], '
|
8
|
+
votes.try(:[], 'up_count') || 0
|
9
9
|
end
|
10
10
|
|
11
11
|
# Get the number of down votes
|
12
12
|
def down_votes_count
|
13
|
-
votes.try(:[], '
|
13
|
+
votes.try(:[], 'down_count') || 0
|
14
14
|
end
|
15
15
|
|
16
16
|
# Get the number of votes
|
17
17
|
def votes_count
|
18
|
-
votes.try(:[], '
|
18
|
+
votes.try(:[], 'count') || 0
|
19
19
|
end
|
20
20
|
|
21
21
|
# Get the votes point
|
22
22
|
def votes_point
|
23
|
-
votes.try(:[], '
|
23
|
+
votes.try(:[], 'point') || 0
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.init(log = false)
|
27
|
-
VOTEABLE.each do |class_name,
|
27
|
+
VOTEABLE.each do |class_name, voteable|
|
28
28
|
klass = class_name.constantize
|
29
|
-
|
29
|
+
klass_voteable = voteable[class_name]
|
30
30
|
puts "Init stats for #{class_name}" if log
|
31
31
|
klass.collection.update({:votes => nil}, {
|
32
32
|
'$set' => { :votes => VOTES_DEFAULT_ATTRIBUTES }
|
@@ -44,46 +44,46 @@ module Mongoid
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.remake_stats(log)
|
47
|
-
VOTEABLE.each do |class_name,
|
47
|
+
VOTEABLE.each do |class_name, voteable|
|
48
48
|
klass = class_name.constantize
|
49
|
-
|
49
|
+
klass_voteable = voteable[class_name]
|
50
50
|
puts "Generating stats for #{class_name}" if log
|
51
51
|
klass.all.each{ |doc|
|
52
|
-
doc.remake_stats(
|
52
|
+
doc.remake_stats(klass_voteable)
|
53
53
|
}
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def remake_stats(
|
57
|
+
def remake_stats(voteable)
|
58
58
|
up_count = up_voter_ids.length
|
59
59
|
down_count = down_voter_ids.length
|
60
60
|
|
61
61
|
update_attributes(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
'votes.up_count' => up_count,
|
63
|
+
'votes.down_count' => down_count,
|
64
|
+
'votes.count' => up_count + down_count,
|
65
|
+
'votes.point' => voteable[:up]*up_count + voteable[:down]*down_count
|
66
66
|
)
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.update_parent_stats(log)
|
70
|
-
VOTEABLE.each do |class_name,
|
70
|
+
VOTEABLE.each do |class_name, voteable|
|
71
71
|
klass = class_name.constantize
|
72
|
-
|
72
|
+
voteable.each do |parent_class_name, parent_voteable|
|
73
73
|
relation_metadata = klass.relations[parent_class_name.underscore]
|
74
74
|
if relation_metadata
|
75
75
|
parent_class = parent_class_name.constantize
|
76
76
|
foreign_key = relation_metadata.foreign_key
|
77
77
|
puts "Updating stats for #{class_name} > #{parent_class_name}" if log
|
78
78
|
klass.all.each{ |doc|
|
79
|
-
doc.update_parent_stats(parent_class, foreign_key,
|
79
|
+
doc.update_parent_stats(parent_class, foreign_key, parent_voteable)
|
80
80
|
}
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
def update_parent_stats(parent_class, foreign_key,
|
86
|
+
def update_parent_stats(parent_class, foreign_key, voteable)
|
87
87
|
parent_id = read_attribute(foreign_key.to_sym)
|
88
88
|
if parent_id
|
89
89
|
up_count = up_voter_ids.length
|
@@ -92,19 +92,19 @@ module Mongoid
|
|
92
92
|
return if up_count == 0 && down_count == 0
|
93
93
|
|
94
94
|
inc_options = {
|
95
|
-
|
95
|
+
'votes.point' => voteable[:up]*up_count + voteable[:down]*down_count
|
96
96
|
}
|
97
97
|
|
98
|
-
unless
|
98
|
+
unless voteable[:update_counters] == false
|
99
99
|
inc_options.merge!(
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
'votes.count' => up_count + down_count,
|
101
|
+
'votes.up_count' => up_count,
|
102
|
+
'votes.down_count' => down_count
|
103
103
|
)
|
104
104
|
end
|
105
105
|
|
106
106
|
parent_class.collection.update(
|
107
|
-
{
|
107
|
+
{ '_id' => parent_id },
|
108
108
|
{ '$inc' => inc_options }
|
109
109
|
)
|
110
110
|
end
|
@@ -3,57 +3,55 @@ module Mongoid
|
|
3
3
|
|
4
4
|
class Votes
|
5
5
|
include Mongoid::Document
|
6
|
-
field :
|
7
|
-
field :
|
8
|
-
field :
|
9
|
-
field :
|
10
|
-
field :
|
11
|
-
field :
|
6
|
+
field :up, :type => Array, :default => []
|
7
|
+
field :down, :type => Array, :default => []
|
8
|
+
field :up_count, :type => Integer, :default => 0
|
9
|
+
field :down_count, :type => Integer, :default => 0
|
10
|
+
field :count, :type => Integer, :default => 0
|
11
|
+
field :point, :type => Integer, :default => 0
|
12
12
|
end
|
13
|
-
|
14
|
-
UP_VOTER_IDS = 'votes.u'
|
15
|
-
DOWN_VOTER_IDS = 'votes.d'
|
16
|
-
UP_VOTES_COUNT = 'votes.uc'
|
17
|
-
DOWN_VOTES_COUNT = 'votes.dc'
|
18
|
-
VOTES_COUNT = 'votes.c'
|
19
|
-
VOTES_POINT = 'votes.p'
|
20
13
|
|
21
14
|
VOTES_DEFAULT_ATTRIBUTES = Votes.new.attributes
|
22
15
|
VOTES_DEFAULT_ATTRIBUTES.delete('_id')
|
23
16
|
|
24
17
|
def self.migrate_old_votes(log = false)
|
25
|
-
VOTEABLE.each do |class_name,
|
18
|
+
VOTEABLE.each do |class_name, voteable|
|
26
19
|
klass = class_name.constantize
|
27
|
-
|
20
|
+
klass_voteable = voteable[class_name]
|
28
21
|
puts "* Migrating old vote data for #{class_name} ..." if log
|
29
|
-
|
22
|
+
|
30
23
|
klass.all.each do |doc|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
# Version 0.6.x use very short field names (u, d, uc, dc, c, p) to minimize
|
25
|
+
# votes storage but it's not human friendly
|
26
|
+
# Version >= 0.7.0 use readable field names (up, down, up_count, down_count,
|
27
|
+
# count, point)
|
28
|
+
votes = doc['votes'] || doc['voteable'] || {}
|
29
|
+
up_voter_ids = votes['u'] || votes['up'] || votes['up_voter_ids'] || doc['up_voter_ids'] || []
|
30
|
+
down_voter_ids = votes['d'] || votes['down'] || votes['down_voter_ids'] || doc['down_voter_ids'] || []
|
31
|
+
|
35
32
|
up_count = up_voter_ids.size
|
36
33
|
down_count = down_voter_ids.size
|
34
|
+
|
37
35
|
klass.collection.update({ :_id => doc.id }, {
|
38
36
|
'$set' => {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
'votes' => {
|
38
|
+
'up' => up_voter_ids,
|
39
|
+
'down' => down_voter_ids,
|
40
|
+
'up_count' => up_count,
|
41
|
+
'down_count' => down_count,
|
42
|
+
'count' => up_count + down_count,
|
43
|
+
'point' => klass_voteable[:up]*up_count + klass_voteable[:down]*down_count
|
46
44
|
}
|
47
45
|
},
|
48
46
|
'$unset' => {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
'up_voter_ids' => true,
|
48
|
+
'down_voter_ids' => true,
|
49
|
+
'votes_count' => true,
|
50
|
+
'votes_point' => true,
|
51
|
+
'voteable' => true
|
53
52
|
}
|
54
53
|
})
|
55
54
|
end
|
56
|
-
puts " #{count} objects migrated." if log
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voteable_mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 0
|
10
|
+
version: 0.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alex Nguyen
|