voteable_mongoid 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm_gemset_create_on_use_flag=1
2
+ rvm use 1.9.2@mongoid
data/CHANGELOG.rdoc CHANGED
@@ -1,10 +1,16 @@
1
+ == 0.7.3
2
+ * Add :return_votee => true option to vote function to warranty always return voteable object
3
+ * Add Voteable.voted?, Voteable.up_voted?, Voteable.down_voted?
4
+ * Update parent for ManyToMany relationship
5
+ * Refactor
6
+
1
7
  == 0.7.2
2
8
  * Use Collection#find_and_modify to retrieve updated votes data and parent_ids (don't need an extra query to get parent_ids)
3
9
 
4
10
  == 0.7.1
5
- * Refactor & cleanup source code
6
- * Better doc
7
11
  * Add votee#voted_by?(voter or voter_id)
12
+ * Better doc
13
+ * Refactor & cleanup source code
8
14
 
9
15
  == 0.7.0
10
16
  * Use readable field names (up, down, up_count, down_count, count, point) instead of very short field names (u, d, uc, dc, c, p)
data/README.rdoc CHANGED
@@ -3,7 +3,9 @@
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 uses only one database request per collection to do both data validation and data update.
6
+ Initial idea is based on http://cookbook.mongodb.org/patterns/votes
7
+
8
+ Voteable Mongoid is built for speed. It uses only one database request per collection to validate data, update data, and get updated data.
7
9
 
8
10
  Sample app at https://github.com/vinova/simple_qa
9
11
 
@@ -30,7 +32,7 @@ post.rb
30
32
  # set points for each vote
31
33
  voteable self, :up => +1, :down => -1
32
34
 
33
- references_many :comments
35
+ has_many :comments
34
36
  end
35
37
 
36
38
  comment.rb
@@ -41,7 +43,7 @@ comment.rb
41
43
  include Mongoid::Document
42
44
  include Mongoid::Voteable
43
45
 
44
- referenced_in :post
46
+ belongs_to :post
45
47
 
46
48
  voteable self, :up => +1, :down => -3
47
49
 
@@ -59,11 +61,12 @@ user.rb
59
61
  === Making a vote
60
62
 
61
63
  @user.vote(@post, :up)
62
- # is equivalent to
64
+
65
+ Is equivalent to
63
66
  @user.vote(:votee => @post, :value => :up)
64
67
  @post.vote(:voter => @user, :value => :up)
65
68
 
66
- # In case you don't need to init voter and / or votee objects you can
69
+ In case you don't need to init voter and / or votee objects you can
67
70
  @user.vote(:votee_type => 'Post', :votee_id => post_id, :value => :down)
68
71
  @post.vote(:voter_id => user_id, :value => :up)
69
72
  Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up)
@@ -72,10 +75,19 @@ user.rb
72
75
 
73
76
  @user.unvote(@comment)
74
77
 
75
- === If have full information you do not need to init voter and votee object
78
+ === If have voter_id, votee_id and vote value you don't need to init voter and votee objects (suitable for API calls)
79
+
80
+ New vote
81
+ Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up)
76
82
 
83
+ Re-vote
77
84
  Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :revote => true)
85
+
86
+ Un-vote
78
87
  Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :unvote => true)
88
+
89
+ In-case you need updated voteable object, add :return_votee => true
90
+ votee = Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :return_votee => true)
79
91
 
80
92
  === Getting vote_value
81
93
 
@@ -126,8 +138,8 @@ Ruby
126
138
 
127
139
  == Credits
128
140
 
129
- * Alex N. - Author
130
- * Stefan N. - Unvoting
141
+ * Alex Nguyen (alex@vinova.sg) - Author
142
+ * Stefan Nguyen (stefan@vinova.sg) - Unvoting
131
143
 
132
144
  Copyright (c) 2010-2011 Vinova Pte Ltd (http://vinova.sg)
133
145
 
data/TODO CHANGED
@@ -1,2 +1,2 @@
1
1
  * Option hash validations
2
-
2
+ * Refactor specs
@@ -1,3 +1,3 @@
1
1
  module VoteableMongoid
2
- VERSION = '0.7.2'
2
+ VERSION = '0.7.3'
3
3
  end
@@ -10,28 +10,25 @@ module Mongoid
10
10
  # - :votee_id: the votee document id
11
11
  # - :voter_id: the voter document id
12
12
  # - :value: :up or :down
13
- # - :revote: change from vote up to vote down
14
- # - :unvote: unvote the vote value (:up or :down)
13
+ # - :revote: if true change vote vote from :up to :down and vise versa
14
+ # - :unvote: if true undo the voting
15
+ # - :return: if true always return updated voteable object
16
+ #
17
+ # @return [votes, false, nil]
15
18
  def vote(options)
16
- options.symbolize_keys!
17
- options[:votee_id] ||= options[:votee].id
18
- options[:votee_id] = BSON::ObjectId(options[:votee_id]) if options[:votee_id].is_a?(String)
19
- options[:voter_id] = BSON::ObjectId(options[:voter_id]) if options[:voter_id].is_a?(String)
20
- options[:value] = options[:value].to_sym
19
+ validate_and_normalize_vote_options(options)
21
20
  options[:voteable] = VOTEABLE[name][name]
22
21
 
23
- update_parents = options[:voteable][:update_parents]
24
-
25
22
  if options[:voteable]
26
23
  query, update = if options[:revote]
27
- revote(options)
24
+ revote_query_and_update(options)
28
25
  elsif options[:unvote]
29
- unvote(options)
26
+ unvote_query_and_update(options)
30
27
  else
31
- new_vote(options)
28
+ new_vote_query_and_update(options)
32
29
  end
33
30
 
34
- if options[:votee] || update_parents
31
+ if options[:voteable][:update_parents] || options[:votee] || options[:return_votee]
35
32
  # If votee exits or need to update parent
36
33
  # use Collection#find_and_modify to retrieve updated votes data and parent_ids
37
34
  begin
@@ -42,9 +39,11 @@ module Mongoid
42
39
  )
43
40
  # Update new votes data
44
41
  options[:votee].write_attribute('votes', doc['votes']) if options[:votee]
45
- update_parent_votes(doc, options) if update_parents
42
+ update_parent_votes(doc, options) if options[:voteable][:update_parents]
43
+ return options[:votee] || new(doc)
46
44
  rescue
47
45
  # Don't update parents if operation fail or no matching object found
46
+ return false
48
47
  end
49
48
  else
50
49
  # Just update and don't care the result
@@ -55,7 +54,14 @@ module Mongoid
55
54
 
56
55
 
57
56
  private
58
- def new_vote(options)
57
+ def validate_and_normalize_vote_options(options)
58
+ options.symbolize_keys!
59
+ options[:votee_id] = BSON::ObjectId(options[:votee_id]) if options[:votee_id].is_a?(String)
60
+ options[:voter_id] = BSON::ObjectId(options[:voter_id]) if options[:voter_id].is_a?(String)
61
+ options[:value] &&= options[:value].to_sym
62
+ end
63
+
64
+ def new_vote_query_and_update(options)
59
65
  if options[:value] == :up
60
66
  positive_voter_ids = 'votes.up'
61
67
  positive_votes_count = 'votes.up_count'
@@ -80,7 +86,7 @@ module Mongoid
80
86
  end
81
87
 
82
88
 
83
- def revote(options)
89
+ def revote_query_and_update(options)
84
90
  if options[:value] == :up
85
91
  positive_voter_ids = 'votes.up'
86
92
  negative_voter_ids = 'votes.down'
@@ -113,7 +119,7 @@ module Mongoid
113
119
  end
114
120
 
115
121
 
116
- def unvote(options)
122
+ def unvote_query_and_update(options)
117
123
  if options[:value] == :up
118
124
  positive_voter_ids = 'votes.up'
119
125
  negative_voter_ids = 'votes.down'
@@ -142,28 +148,36 @@ module Mongoid
142
148
 
143
149
 
144
150
  def update_parent_votes(doc, options)
145
- value = options[:value]
146
- votee ||= options[:votee]
147
-
148
151
  VOTEABLE[name].each do |class_name, voteable|
149
- # For other class in VOTEABLE options, if is parent of current class
150
- next unless relation_metadata = relations[class_name.underscore]
151
- # If can find current votee foreign_key value for that class
152
- next unless foreign_key_value = doc[relation_metadata.foreign_key.to_s]
152
+ # For other class in VOTEABLE options, if has relationship with current class
153
+ relation_metadata = relations.find{ |x, r| r.class_name == class_name }.try(:last)
154
+ next unless relation_metadata.present?
153
155
 
154
- class_name.constantize.collection.update(
155
- { '_id' => foreign_key_value },
156
- { '$inc' => parent_inc_options(value, voteable, options) }
157
- )
156
+ # If cannot find current votee foreign_key value for that class
157
+ foreign_key_value = doc[relation_metadata.foreign_key.to_s]
158
+ next unless foreign_key_value.present?
159
+
160
+ if relation_metadata.relation == Mongoid::Relations::Referenced::In
161
+ class_name.constantize.collection.update(
162
+ { '_id' => foreign_key_value },
163
+ { '$inc' => parent_inc_options(voteable, options) }
164
+ )
165
+ elsif relation_metadata.relation == Mongoid::Relations::Referenced::ManyToMany
166
+ class_name.constantize.collection.update(
167
+ { '_id' => { '$in' => foreign_key_value } },
168
+ { '$inc' => parent_inc_options(voteable, options) },
169
+ { :multi => true }
170
+ )
171
+ end
158
172
  end
159
173
  end
160
174
 
161
175
 
162
- def parent_inc_options(value, voteable, options)
176
+ def parent_inc_options(voteable, options)
163
177
  inc_options = {}
164
178
 
165
179
  if options[:revote]
166
- if value == :up
180
+ if options[:value] == :up
167
181
  inc_options['votes.point'] = voteable[:up] - voteable[:down]
168
182
  unless voteable[:update_counters] == false
169
183
  inc_options['votes.up_count'] = +1
@@ -178,10 +192,10 @@ module Mongoid
178
192
  end
179
193
 
180
194
  elsif options[:unvote]
181
- inc_options['votes.point'] = -voteable[value]
195
+ inc_options['votes.point'] = -voteable[options[:value]]
182
196
  unless voteable[:update_counters] == false
183
197
  inc_options['votes.count'] = -1
184
- if value == :up
198
+ if options[:value] == :up
185
199
  inc_options['votes.up_count'] = -1
186
200
  else
187
201
  inc_options['votes.down_count'] = -1
@@ -189,10 +203,10 @@ module Mongoid
189
203
  end
190
204
 
191
205
  else # new vote
192
- inc_options['votes.point'] = voteable[value]
206
+ inc_options['votes.point'] = voteable[options[:value]]
193
207
  unless voteable[:update_counters] == false
194
208
  inc_options['votes.count'] = +1
195
- if value == :up
209
+ if options[:value] == :up
196
210
  inc_options['votes.up_count'] = +1
197
211
  else
198
212
  inc_options['votes.down_count'] = +1
@@ -6,8 +6,8 @@ module Mongoid
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- include Document
10
- include Voting
9
+ include ::Mongoid::Document
10
+ include ::Mongoid::Voteable::Voting
11
11
 
12
12
  field :votes, :type => Votes
13
13
 
@@ -50,70 +50,108 @@ module Mongoid
50
50
  VOTEABLE[name][name][:update_parents] = true
51
51
  end
52
52
  end
53
+
54
+ # Check if voter_id do a vote on votee_id
55
+ #
56
+ # @param [Hash] options a hash containings:
57
+ # - :votee_id: the votee document id
58
+ # - :voter_id: the voter document id
59
+ #
60
+ # @return [true, false]
61
+ def voted?(options)
62
+ validate_and_normalize_vote_options(options)
63
+ up_voted?(options) || down_voted?(options)
64
+ end
65
+
66
+ # Check if voter_id do an up vote on votee_id
67
+ #
68
+ # @param [Hash] options a hash containings:
69
+ # - :votee_id: the votee document id
70
+ # - :voter_id: the voter document id
71
+ #
72
+ # @return [true, false]
73
+ def up_voted?(options)
74
+ validate_and_normalize_vote_options(options)
75
+ up_voted_by(options[:voter_id]).where(:_id => options[:votee_id]).count == 1
76
+ end
77
+
78
+ # Check if voter_id do a down vote on votee_id
79
+ #
80
+ # @param [Hash] options a hash containings:
81
+ # - :votee_id: the votee document id
82
+ # - :voter_id: the voter document id
83
+ #
84
+ # @return [true, false]
85
+ def down_voted?(options)
86
+ validate_and_normalize_vote_options(options)
87
+ down_voted_by(options[:voter_id]).where(:_id => options[:votee_id]).count == 1
88
+ end
53
89
  end
54
90
 
55
- # Make a vote on this votee
56
- #
57
- # @param [Hash] options a hash containings:
58
- # - :voter_id: the voter document id
59
- # - :value: vote :up or vote :down
60
- # - :revote: change from vote up to vote down
61
- # - :unvote: unvote the vote value (:up or :down)
62
- def vote(options)
63
- options[:votee_id] = id
64
- options[:votee] = self
65
- options[:voter_id] ||= options[:voter].id
66
-
67
- if options[:unvote]
68
- options[:value] ||= vote_value(options[:voter_id])
69
- else
70
- options[:revote] ||= vote_value(options[:voter_id]).present?
71
- end
91
+ module InstanceMethods
92
+ # Make a vote on this votee
93
+ #
94
+ # @param [Hash] options a hash containings:
95
+ # - :voter_id: the voter document id
96
+ # - :value: vote :up or vote :down
97
+ # - :revote: change from vote up to vote down
98
+ # - :unvote: unvote the vote value (:up or :down)
99
+ def vote(options)
100
+ options[:votee_id] = id
101
+ options[:votee] = self
102
+ options[:voter_id] ||= options[:voter].id
72
103
 
73
- self.class.vote(options)
74
- end
104
+ if options[:unvote]
105
+ options[:value] ||= vote_value(options[:voter_id])
106
+ else
107
+ options[:revote] ||= vote_value(options[:voter_id]).present?
108
+ end
75
109
 
76
- # Get a voted value on this votee
77
- #
78
- # @param [Mongoid Object, BSON::ObjectId] voter is Mongoid object or the id of the voter who made the vote
79
- def vote_value(voter)
80
- voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter.id
81
- return :up if up_voter_ids.include?(voter_id)
82
- return :down if down_voter_ids.include?(voter_id)
83
- end
110
+ self.class.vote(options)
111
+ end
84
112
 
85
- def voted_by?(voter)
86
- !!vote_value(voter)
87
- end
113
+ # Get a voted value on this votee
114
+ #
115
+ # @param [Mongoid Object, BSON::ObjectId] voter is Mongoid object or the id of the voter who made the vote
116
+ def vote_value(voter)
117
+ voter_id = voter.is_a?(BSON::ObjectId) ? voter : voter.id
118
+ return :up if up_voter_ids.include?(voter_id)
119
+ return :down if down_voter_ids.include?(voter_id)
120
+ end
121
+
122
+ def voted_by?(voter)
123
+ !!vote_value(voter)
124
+ end
88
125
 
89
- # Array of up voter ids
90
- def up_voter_ids
91
- votes.try(:[], 'up') || []
92
- end
126
+ # Array of up voter ids
127
+ def up_voter_ids
128
+ votes.try(:[], 'up') || []
129
+ end
93
130
 
94
- # Array of down voter ids
95
- def down_voter_ids
96
- votes.try(:[], 'down') || []
97
- end
131
+ # Array of down voter ids
132
+ def down_voter_ids
133
+ votes.try(:[], 'down') || []
134
+ end
98
135
 
99
- # Get the number of up votes
100
- def up_votes_count
101
- votes.try(:[], 'up_count') || 0
102
- end
136
+ # Get the number of up votes
137
+ def up_votes_count
138
+ votes.try(:[], 'up_count') || 0
139
+ end
103
140
 
104
- # Get the number of down votes
105
- def down_votes_count
106
- votes.try(:[], 'down_count') || 0
107
- end
141
+ # Get the number of down votes
142
+ def down_votes_count
143
+ votes.try(:[], 'down_count') || 0
144
+ end
108
145
 
109
- # Get the number of votes
110
- def votes_count
111
- votes.try(:[], 'count') || 0
112
- end
146
+ # Get the number of votes
147
+ def votes_count
148
+ votes.try(:[], 'count') || 0
149
+ end
113
150
 
114
- # Get the votes point
115
- def votes_point
116
- votes.try(:[], 'point') || 0
151
+ # Get the votes point
152
+ def votes_point
153
+ votes.try(:[], 'point') || 0
154
+ end
117
155
  end
118
156
 
119
157
  end
@@ -1,86 +1,89 @@
1
1
  module Mongoid
2
2
  module Voter
3
3
  extend ActiveSupport::Concern
4
-
5
- # Check to see if this voter voted on the votee or not
6
- #
7
- # @param [Hash, Object] options the hash containing the votee, or the votee itself
8
- # @return [true, false] true if voted, false otherwise
9
- def voted?(options)
10
- unless options.is_a?(Hash)
11
- votee_class = options.class
12
- votee_id = options.id
13
- else
14
- votee = options[:votee]
15
- if votee
16
- votee_class = votee.class
17
- votee_id = votee.id
4
+
5
+ module InstanceMethods
6
+ # Check to see if this voter voted on the votee or not
7
+ #
8
+ # @param [Hash, Object] options the hash containing the votee, or the votee itself
9
+ # @return [true, false] true if voted, false otherwise
10
+ def voted?(options)
11
+ unless options.is_a?(Hash)
12
+ votee_class = options.class
13
+ votee_id = options.id
18
14
  else
19
- votee_class = options[:votee_type].classify.constantize
20
- votee_id = options[:votee_id]
15
+ votee = options[:votee]
16
+ if votee
17
+ votee_class = votee.class
18
+ votee_id = votee.id
19
+ else
20
+ votee_class = options[:votee_type].classify.constantize
21
+ votee_id = options[:votee_id]
22
+ end
21
23
  end
22
- end
23
24
 
24
- votee_class.voted_by(self).where(:_id => votee_id).count == 1
25
- end
25
+ votee_class.voted?(:voter_id => id, :votee_id => votee_id)
26
+ end
26
27
 
27
- # Get the voted value on a votee
28
- #
29
- # @param (see #voted?)
30
- # @return [Symbol, nil] :up or :down or nil if not voted
31
- def vote_value(options)
32
- votee = unless options.is_a?(Hash)
33
- options
34
- else
35
- options[:votee] || options[:votee_type].classify.constantize.only(:votes).where(
36
- :_id => options[:votee_id]
37
- ).first
28
+ # Get the voted value on a votee
29
+ #
30
+ # @param (see #voted?)
31
+ # @return [Symbol, nil] :up or :down or nil if not voted
32
+ def vote_value(options)
33
+ votee = unless options.is_a?(Hash)
34
+ options
35
+ else
36
+ options[:votee] || options[:votee_type].classify.constantize.only(:votes).where(
37
+ :_id => options[:votee_id]
38
+ ).first
39
+ end
40
+ votee.vote_value(_id)
38
41
  end
39
- votee.vote_value(_id)
40
- end
41
42
 
42
- # Cancel the vote on a votee
43
- #
44
- # @param [Object] votee the votee to be unvoted
45
- def unvote(options)
46
- unless options.is_a?(Hash)
47
- options = { :votee => options }
43
+ # Cancel the vote on a votee
44
+ #
45
+ # @param [Object] votee the votee to be unvoted
46
+ def unvote(options)
47
+ unless options.is_a?(Hash)
48
+ options = { :votee => options }
49
+ end
50
+ options[:unvote] = true
51
+ options[:revote] = false
52
+ vote(options)
48
53
  end
49
- options[:unvote] = true
50
- options[:revote] = false
51
- vote(options)
52
- end
53
54
 
54
- # Vote on a votee
55
- #
56
- # @param (see #voted?)
57
- # @param [:up, :down] vote_value vote up or vote down, nil to unvote
58
- def vote(options, value = nil)
59
- if options.is_a?(Hash)
60
- votee = options[:votee]
61
- else
62
- votee = options
63
- options = { :votee => votee, :value => value }
64
- end
55
+ # Vote on a votee
56
+ #
57
+ # @param (see #voted?)
58
+ # @param [:up, :down] vote_value vote up or vote down, nil to unvote
59
+ def vote(options, value = nil)
60
+ if options.is_a?(Hash)
61
+ votee = options[:votee]
62
+ else
63
+ votee = options
64
+ options = { :votee => votee, :value => value }
65
+ end
65
66
 
66
- if votee
67
- options[:votee_id] = votee.id
68
- votee_class = votee.class
69
- else
70
- votee_class = options[:votee_type].classify.constantize
71
- end
67
+ if votee
68
+ options[:votee_id] = votee.id
69
+ votee_class = votee.class
70
+ else
71
+ votee_class = options[:votee_type].classify.constantize
72
+ end
72
73
 
73
- if options[:value].nil?
74
- options[:unvote] = true
75
- options[:value] = vote_value(options)
76
- else
77
- options[:revote] = options.has_key?(:revote) ? !options[:revote].blank? : voted?(options)
78
- end
74
+ if options[:value].nil?
75
+ options[:unvote] = true
76
+ options[:value] = vote_value(options)
77
+ else
78
+ options[:revote] = options.has_key?(:revote) ? !options[:revote].blank? : voted?(options)
79
+ end
79
80
 
80
- options[:voter] = self
81
- options[:voter_id] = id
81
+ options[:voter] = self
82
+ options[:voter_id] = id
82
83
 
83
- ( votee || votee_class ).vote(options)
84
+ ( votee || votee_class ).vote(options)
85
+ end
84
86
  end
87
+
85
88
  end
86
89
  end
@@ -0,0 +1,8 @@
1
+ class Category
2
+ include Mongoid::Document
3
+ include Mongoid::Voteable
4
+
5
+ field :name
6
+
7
+ has_and_belongs_to_many :posts
8
+ end
@@ -1,11 +1,13 @@
1
1
  require 'post'
2
2
 
3
3
  class Comment
4
- include Mongoid::Document
5
4
  include Mongoid::Voteable
6
-
7
- referenced_in :post
5
+ include Mongoid::Document
6
+
7
+ field :content
8
+
9
+ belongs_to :post
8
10
 
9
11
  voteable self, :up => +1, :down => -3
10
- voteable Post, :up => +2, :down => -1 #, :not_update_counters => true
12
+ voteable Post, :up => +2, :down => -1
11
13
  end
data/spec/models/post.rb CHANGED
@@ -2,7 +2,12 @@ class Post
2
2
  include Mongoid::Document
3
3
  include Mongoid::Voteable
4
4
 
5
- voteable self, :up => +1, :down => -1
5
+ field :title
6
+ field :content
6
7
 
7
- references_many :comments
8
+ has_and_belongs_to_many :categories
9
+ has_many :comments
10
+
11
+ voteable self, :up => +1, :down => -1
12
+ voteable Category, :up => +3, :down => -5, :update_counters => false
8
13
  end
data/spec/spec_helper.rb CHANGED
@@ -29,3 +29,4 @@ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file)
29
29
  User.collection.drop
30
30
  Post.collection.drop
31
31
  Comment.collection.drop
32
+ Category.collection.drop
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Mongoid::Voteable::Tasks do
4
+ describe 'Mongoid::Voteable::Tasks.init_stats' do
5
+ before :all do
6
+ @post1 = Post.create!
7
+ @post2 = Post.create!
8
+ end
9
+
10
+ it 'after create votes has default value' do
11
+ @post1.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
12
+ @post2.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
13
+ end
14
+
15
+ it 'reset votes data' do
16
+ @post1.votes = nil
17
+ @post1.save
18
+
19
+ @post2.votes = nil
20
+ @post2.save
21
+ end
22
+
23
+ it 'init_stats recover votes default value' do
24
+ Mongoid::Voteable::Tasks.init_stats
25
+
26
+ @post1.reload
27
+ @post2.reload
28
+
29
+ @post1.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
30
+ @post2.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
31
+ end
32
+ end
33
+ end
@@ -1,17 +1,34 @@
1
- require "spec_helper"
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Mongoid::Voteable do
4
4
  before :all do
5
+ @category1 = Category.create!(:name => 'xyz')
6
+ @category2 = Category.create!(:name => 'abc')
7
+
5
8
  @post1 = Post.create!
6
9
  @post2 = Post.create!
7
10
 
11
+ @post1.categories << @category1
12
+ @category2.posts << @post1
13
+
8
14
  @comment = @post2.comments.create!
15
+
9
16
  @user1 = User.create!
10
17
  @user2 = User.create!
11
18
  end
12
19
 
13
20
  context "just created" do
14
- it 'voteable votes_count, votes_point should be zero' do
21
+ it 'votes_count, up_votes_count, down_votes_count, votes_point should be zero' do
22
+ @category1.up_votes_count.should == 0
23
+ @category1.down_votes_count.should == 0
24
+ @category1.votes_count.should == 0
25
+ @category1.votes_point.should == 0
26
+
27
+ @category2.up_votes_count.should == 0
28
+ @category2.down_votes_count.should == 0
29
+ @category2.votes_count.should == 0
30
+ @category2.votes_point.should == 0
31
+
15
32
  @post1.up_votes_count.should == 0
16
33
  @post1.down_votes_count.should == 0
17
34
  @post1.votes_count.should == 0
@@ -21,49 +38,51 @@ describe Mongoid::Voteable do
21
38
  @post2.down_votes_count.should == 0
22
39
  @post2.votes_count.should == 0
23
40
  @post2.votes_point.should == 0
41
+
42
+ @comment.up_votes_count.should == 0
43
+ @comment.down_votes_count.should == 0
44
+ @comment.votes_count.should == 0
45
+ @comment.votes_point.should == 0
24
46
  end
25
47
 
26
- it 'voteable up_voter_ids, down_voter_ids should be empty' do
48
+ it 'up_voter_ids, down_voter_ids should be empty' do
49
+ @category1.up_voter_ids.should be_empty
50
+ @category1.down_voter_ids.should be_empty
51
+
52
+ @category2.up_voter_ids.should be_empty
53
+ @category2.down_voter_ids.should be_empty
54
+
27
55
  @post1.up_voter_ids.should be_empty
28
56
  @post1.down_voter_ids.should be_empty
29
57
 
30
58
  @post2.up_voter_ids.should be_empty
31
59
  @post2.down_voter_ids.should be_empty
60
+
61
+ @comment.up_voter_ids.should be_empty
62
+ @comment.down_voter_ids.should be_empty
32
63
  end
33
64
 
34
- it 'posts voted voter should be empty' do
65
+ it 'voted by voter should be empty' do
66
+ Category.voted_by(@user1).should be_empty
67
+ Category.voted_by(@user2).should be_empty
68
+
35
69
  Post.voted_by(@user1).should be_empty
36
70
  Post.voted_by(@user2).should be_empty
37
- end
38
-
39
- it 'test init stats' do
40
- @post1.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
41
- @post2.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
42
-
43
- @post1.votes = nil
44
- @post1.save
45
-
46
- @post2.votes = nil
47
- @post2.save
48
71
 
49
- Mongoid::Voteable::Tasks.init_stats
50
-
51
- @post1.reload
52
- @post2.reload
53
-
54
- @post1.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
55
- @post2.votes.should == Mongoid::Voteable::Votes::DEFAULT_ATTRIBUTES
72
+ Comment.voted_by(@user1).should be_empty
73
+ Comment.voted_by(@user2).should be_empty
56
74
  end
57
-
58
- it 'revote has no effect' do
75
+
76
+ it 'revote post1 has no effect' do
59
77
  @post1.vote(:revote => true, :voter => @user1, :value => 'up')
60
- @post1.reload
61
78
 
62
79
  @post1.up_votes_count.should == 0
63
80
  @post1.down_votes_count.should == 0
64
81
  @post1.votes_count.should == 0
65
82
  @post1.votes_point.should == 0
66
-
83
+ end
84
+
85
+ it 'revote post2 has no effect' do
67
86
  Post.vote(:revote => true, :votee_id => @post2.id, :voter_id => @user2.id, :value => :down)
68
87
  @post2.reload
69
88
 
@@ -76,10 +95,24 @@ describe Mongoid::Voteable do
76
95
 
77
96
  context 'user1 vote up post1 the first time' do
78
97
  before :all do
79
- Post.vote(:votee => @post1, :voter_id => @user1.id, :value => :up)
98
+ @return = @post1.vote(:voter_id => @user1.id, :value => :up, :return_votee => true)
80
99
  end
81
100
 
82
- it '' do
101
+ it 'validates return post' do
102
+ @return.votes.should == {
103
+ 'up' => [@user1.id],
104
+ 'down' => [],
105
+ 'up_count' => 1,
106
+ 'down_count' => 0,
107
+ 'count' => 1,
108
+ 'point' => 1
109
+ }
110
+
111
+ @return.should_not be_new_record
112
+ @return.should be_is_a(Post)
113
+ end
114
+
115
+ it 'validates' do
83
116
  @post1.up_votes_count.should == 1
84
117
  @post1.down_votes_count.should == 0
85
118
  @post1.votes_count.should == 1
@@ -92,6 +125,18 @@ describe Mongoid::Voteable do
92
125
 
93
126
  Post.voted_by(@user1).to_a.should == [ @post1 ]
94
127
  Post.voted_by(@user2).to_a.should be_empty
128
+
129
+ @category1.reload
130
+ @category1.up_votes_count.should == 0
131
+ @category1.down_votes_count.should == 0
132
+ @category1.votes_count.should == 0
133
+ @category1.votes_point.should == 3
134
+
135
+ @category2.reload
136
+ @category2.up_votes_count.should == 0
137
+ @category2.down_votes_count.should == 0
138
+ @category2.votes_count.should == 0
139
+ @category2.votes_point.should == 3
95
140
  end
96
141
 
97
142
  it 'user1 vote post1 has no effect' do
@@ -113,18 +158,39 @@ describe Mongoid::Voteable do
113
158
  @post1.reload
114
159
  end
115
160
 
116
- it '' do
161
+ it 'post1 up_votes_count is the same' do
117
162
  @post1.up_votes_count.should == 1
163
+ end
164
+
165
+ it 'post1 vote_value on user1 is the same' do
166
+ @post1.vote_value(@user1.id).should == :up
167
+ end
168
+
169
+ it 'down_votes_count, votes_count, and votes_point changed' do
118
170
  @post1.down_votes_count.should == 1
119
171
  @post1.votes_count.should == 2
120
172
  @post1.votes_point.should == 0
121
-
122
- @post1.vote_value(@user1.id).should == :up
123
173
  @post1.vote_value(@user2.id).should == :down
124
-
174
+ end
175
+
176
+ it 'posts voted_by user1, user2 is post1 only' do
125
177
  Post.voted_by(@user1).to_a.should == [ @post1 ]
126
178
  Post.voted_by(@user2).to_a.should == [ @post1 ]
127
179
  end
180
+
181
+ it 'categories votes' do
182
+ @category1.reload
183
+ @category1.up_votes_count.should == 0
184
+ @category1.down_votes_count.should == 0
185
+ @category1.votes_count.should == 0
186
+ @category1.votes_point.should == -2
187
+
188
+ @category2.reload
189
+ @category2.up_votes_count.should == 0
190
+ @category2.down_votes_count.should == 0
191
+ @category2.votes_count.should == 0
192
+ @category2.votes_point.should == -2
193
+ end
128
194
  end
129
195
 
130
196
  context 'user1 change vote on post1 from up to down' do
@@ -134,7 +200,7 @@ describe Mongoid::Voteable do
134
200
  @post1.reload
135
201
  end
136
202
 
137
- it '' do
203
+ it 'validates' do
138
204
  @post1.up_votes_count.should == 0
139
205
  @post1.down_votes_count.should == 2
140
206
  @post1.votes_count.should == 2
@@ -153,7 +219,7 @@ describe Mongoid::Voteable do
153
219
  @post2.vote(:voter_id => @user1.id, :value => :down)
154
220
  end
155
221
 
156
- it '' do
222
+ it 'validates' do
157
223
  @post2.up_votes_count.should == 0
158
224
  @post2.down_votes_count.should == 1
159
225
  @post2.votes_count.should == 1
@@ -173,7 +239,7 @@ describe Mongoid::Voteable do
173
239
  @post2.reload
174
240
  end
175
241
 
176
- it '' do
242
+ it 'validates' do
177
243
  @post2.up_votes_count.should == 1
178
244
  @post2.down_votes_count.should == 0
179
245
  @post2.votes_count.should == 1
@@ -194,7 +260,7 @@ describe Mongoid::Voteable do
194
260
  @post2.reload
195
261
  end
196
262
 
197
- it '' do
263
+ it 'validates' do
198
264
  @post2.up_votes_count.should == 2
199
265
  @post2.down_votes_count.should == 0
200
266
  @post2.votes_count.should == 2
@@ -215,7 +281,7 @@ describe Mongoid::Voteable do
215
281
  @post2.reload
216
282
  end
217
283
 
218
- it '' do
284
+ it 'validates' do
219
285
  @post2.up_votes_count.should == 1
220
286
  @post2.down_votes_count.should == 1
221
287
  @post2.votes_count.should == 2
@@ -249,7 +315,7 @@ describe Mongoid::Voteable do
249
315
  @post1.reload
250
316
  end
251
317
 
252
- it "" do
318
+ it 'validates' do
253
319
  @post1.up_votes_count.should == 0
254
320
  @post1.down_votes_count.should == 1
255
321
  @post1.votes_count.should == 1
@@ -1,4 +1,4 @@
1
- require "spec_helper"
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Mongoid::Voter do
4
4
  before :all do
@@ -10,7 +10,7 @@ describe Mongoid::Voter do
10
10
  end
11
11
 
12
12
  context "just created" do
13
- it '' do
13
+ it 'validates' do
14
14
  Post.voted_by(@user1).should be_empty
15
15
  Post.up_voted_by(@user1).should be_empty
16
16
  Post.down_voted_by(@user1).should be_empty
@@ -39,7 +39,7 @@ describe Mongoid::Voter do
39
39
  @post1.reload
40
40
  end
41
41
 
42
- it '' do
42
+ it 'validates' do
43
43
  @post1.votes_count.should == 1
44
44
  @post1.votes_point.should == 1
45
45
 
@@ -72,7 +72,7 @@ describe Mongoid::Voter do
72
72
  @post1.reload
73
73
  end
74
74
 
75
- it '' do
75
+ it 'validates' do
76
76
  @post1.votes_count.should == 2
77
77
  @post1.votes_point.should == 0
78
78
 
@@ -92,7 +92,7 @@ describe Mongoid::Voter do
92
92
  @post1.reload
93
93
  end
94
94
 
95
- it '' do
95
+ it 'validates' do
96
96
  @post1.votes_count.should == 2
97
97
  @post1.votes_point.should == -2
98
98
 
@@ -110,7 +110,7 @@ describe Mongoid::Voter do
110
110
  @post2.reload
111
111
  end
112
112
 
113
- it '' do
113
+ it 'validates' do
114
114
  @post2.votes_count.should == 1
115
115
  @post2.votes_point.should == -1
116
116
 
@@ -127,7 +127,7 @@ describe Mongoid::Voter do
127
127
  @post2.reload
128
128
  end
129
129
 
130
- it '' do
130
+ it 'validates' do
131
131
  @post2.votes_count.should == 1
132
132
  @post2.votes_point.should == 1
133
133
 
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency 'mongoid', '~> 2.0.0'
16
16
 
17
17
  s.add_development_dependency 'rspec'
18
+ s.add_development_dependency 'bson_ext'
18
19
 
19
20
  s.rubyforge_project = "voteable_mongoid"
20
21
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: voteable_mongoid
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.7.2
5
+ version: 0.7.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Nguyen
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-04 00:00:00 +08:00
14
- default_executable:
13
+ date: 2011-04-24 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: mongoid
@@ -35,6 +34,17 @@ dependencies:
35
34
  version: "0"
36
35
  type: :development
37
36
  version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: bson_ext
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
38
48
  description: Add Up / Down Voting for Mongoid (built for speed by using one Mongodb update-in-place for each collection when provided enough information)
39
49
  email:
40
50
  - alex@vinova.sg
@@ -46,6 +56,7 @@ extra_rdoc_files: []
46
56
 
47
57
  files:
48
58
  - .gitignore
59
+ - .rvmrc
49
60
  - .watchr
50
61
  - CHANGELOG.rdoc
51
62
  - Gemfile
@@ -62,14 +73,15 @@ files:
62
73
  - lib/voteable_mongoid/voteable/voting.rb
63
74
  - lib/voteable_mongoid/voter.rb
64
75
  - spec/.rspec
76
+ - spec/models/category.rb
65
77
  - spec/models/comment.rb
66
78
  - spec/models/post.rb
67
79
  - spec/models/user.rb
68
80
  - spec/spec_helper.rb
81
+ - spec/voteable_mongoid/tasks_spec.rb
69
82
  - spec/voteable_mongoid/voteable_spec.rb
70
83
  - spec/voteable_mongoid/voter_spec.rb
71
84
  - voteable_mongoid.gemspec
72
- has_rdoc: true
73
85
  homepage: https://github.com/vinova/voteable_mongoid
74
86
  licenses: []
75
87
 
@@ -93,14 +105,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
105
  requirements: []
94
106
 
95
107
  rubyforge_project: voteable_mongoid
96
- rubygems_version: 1.6.2
108
+ rubygems_version: 1.7.2
97
109
  signing_key:
98
110
  specification_version: 3
99
111
  summary: Add Up / Down Voting for Mongoid
100
112
  test_files:
113
+ - spec/models/category.rb
101
114
  - spec/models/comment.rb
102
115
  - spec/models/post.rb
103
116
  - spec/models/user.rb
104
117
  - spec/spec_helper.rb
118
+ - spec/voteable_mongoid/tasks_spec.rb
105
119
  - spec/voteable_mongoid/voteable_spec.rb
106
120
  - spec/voteable_mongoid/voter_spec.rb