voteable_mongoid 0.6.4 → 0.7.0
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/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
|