voteable_mongoid 0.7.2 → 0.7.3

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/.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