voteable_mongoid 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == 0.7.4
2
+ * Add Voteable#up_voters(VoterClass), Voteable#down_voters(VoterClass), Voteable#voters(VoterClass)
3
+ * Add Voter scopes: Voter.up_voted_for(voteable_object), Voter.down_voted_for(voteable_object), Voter.voted_for(voteable_object)
4
+ * Add voteable ..., :index => true options
5
+ * Optimization on unvote and revote validations
6
+ * Fix for :up & :down points are nil in rake tasks
7
+
1
8
  == 0.7.3
2
9
  * Add :return_votee => true option to vote function to warranty always return voteable object
3
10
  * Add Voteable.voted?, Voteable.up_voted?, Voteable.down_voted?
@@ -1,3 +1,3 @@
1
1
  module VoteableMongoid
2
- VERSION = '0.7.3'
2
+ VERSION = '0.7.4'
3
3
  end
@@ -46,8 +46,12 @@ module Mongoid
46
46
  def voteable(klass = self, options = nil)
47
47
  VOTEABLE[name] ||= {}
48
48
  VOTEABLE[name][klass.name] ||= options
49
- if klass != self
50
- VOTEABLE[name][name][:update_parents] = true
49
+ if klass == self
50
+ if options[:index] == true
51
+ create_voteable_indexes
52
+ end
53
+ else
54
+ VOTEABLE[name][name][:update_parents] ||= true
51
55
  end
52
56
  end
53
57
 
@@ -86,6 +90,25 @@ module Mongoid
86
90
  validate_and_normalize_vote_options(options)
87
91
  down_voted_by(options[:voter_id]).where(:_id => options[:votee_id]).count == 1
88
92
  end
93
+
94
+ private
95
+ def create_voteable_indexes
96
+ class_eval do
97
+ # Compound index _id and voters.up, _id and voters.down
98
+ # to make up_voted_by, down_voted_by, voted_by scopes and voting faster
99
+ # Should run in background since it introduce new index value and
100
+ # while waiting to build, the system can use _id for voting
101
+ # http://www.mongodb.org/display/DOCS/Indexing+as+a+Background+Operation
102
+ index [['votes.up', 1], ['_id', 1]], :unique => true, :background => true
103
+ index [['votes.down', 1], ['_id', 1]], :unique => true, :background => true
104
+
105
+ # Index counters and point for desc ordering
106
+ index [['votes.count', -1]]
107
+ index [['votes.up_count', -1]]
108
+ index [['votes.down_count', -1]]
109
+ index [['votes.point', -1]]
110
+ end
111
+ end
89
112
  end
90
113
 
91
114
  module InstanceMethods
@@ -133,6 +156,11 @@ module Mongoid
133
156
  votes.try(:[], 'down') || []
134
157
  end
135
158
 
159
+ # Array of voter ids
160
+ def voter_ids
161
+ up_voter_ids + down_voter_ids
162
+ end
163
+
136
164
  # Get the number of up votes
137
165
  def up_votes_count
138
166
  votes.try(:[], 'up_count') || 0
@@ -152,7 +180,21 @@ module Mongoid
152
180
  def votes_point
153
181
  votes.try(:[], 'point') || 0
154
182
  end
183
+
184
+ # Get up voters
185
+ def up_voters(klass)
186
+ klass.where(:_id => { '$in' => up_voter_ids })
187
+ end
188
+
189
+ # Get down voters
190
+ def down_voters(klass)
191
+ klass.where(:_id => { '$in' => down_voter_ids })
192
+ end
193
+
194
+ # Get voters
195
+ def voters(klass)
196
+ klass.where(:_id => { '$in' => voter_ids })
197
+ end
155
198
  end
156
-
157
199
  end
158
200
  end
@@ -59,7 +59,7 @@ module Mongoid
59
59
  'up_count' => up_count,
60
60
  'down_count' => down_count,
61
61
  'count' => up_count + down_count,
62
- 'point' => voteable[:up]*up_count + voteable[:down]*down_count
62
+ 'point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
63
63
  }
64
64
  },
65
65
  '$unset' => {
@@ -94,7 +94,7 @@ module Mongoid
94
94
  'votes.up_count' => up_count,
95
95
  'votes.down_count' => down_count,
96
96
  'votes.count' => up_count + down_count,
97
- 'votes.point' => voteable[:up]*up_count + voteable[:down]*down_count
97
+ 'votes.point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
98
98
  )
99
99
  end
100
100
 
@@ -126,7 +126,7 @@ module Mongoid
126
126
  return if up_count == 0 && down_count == 0
127
127
 
128
128
  inc_options = {
129
- 'votes.point' => voteable[:up]*up_count + voteable[:down]*down_count
129
+ 'votes.point' => voteable[:up].to_i*up_count + voteable[:down].to_i*down_count
130
130
  }
131
131
 
132
132
  unless voteable[:update_counters] == false
@@ -78,10 +78,11 @@ module Mongoid
78
78
  }, {
79
79
  # then update
80
80
  '$push' => { positive_voter_ids => options[:voter_id] },
81
- '$inc' => {
81
+ '$inc' => {
82
82
  'votes.count' => +1,
83
83
  positive_votes_count => +1,
84
- 'votes.point' => options[:voteable][options[:value]] }
84
+ 'votes.point' => options[:voteable][options[:value]]
85
+ }
85
86
  }
86
87
  end
87
88
 
@@ -104,7 +105,9 @@ module Mongoid
104
105
  return {
105
106
  # Validate voter_id did a vote with value for votee_id
106
107
  :_id => options[:votee_id],
107
- positive_voter_ids => { '$ne' => options[:voter_id] },
108
+ # Can skip $ne validation since creating a new vote
109
+ # already warranty that a voter can vote one only
110
+ # positive_voter_ids => { '$ne' => options[:voter_id] },
108
111
  negative_voter_ids => options[:voter_id]
109
112
  }, {
110
113
  # then update
@@ -133,7 +136,9 @@ module Mongoid
133
136
  return {
134
137
  :_id => options[:votee_id],
135
138
  # Validate if voter_id did a vote with value for votee_id
136
- negative_voter_ids => { '$ne' => options[:voter_id] },
139
+ # Can skip $ne validation since creating a new vote
140
+ # already warranty that a voter can vote one only
141
+ # negative_voter_ids => { '$ne' => options[:voter_id] },
137
142
  positive_voter_ids => options[:voter_id]
138
143
  }, {
139
144
  # then update
@@ -1,7 +1,15 @@
1
1
  module Mongoid
2
2
  module Voter
3
3
  extend ActiveSupport::Concern
4
-
4
+
5
+ included do
6
+ include ::Mongoid::Document
7
+
8
+ scope :up_voted_for, lambda { |votee| where(:_id => { '$in' => votee.up_voter_ids }) }
9
+ scope :down_voted_for, lambda { |votee| where(:_id => { '$in' => votee.down_voter_ids }) }
10
+ scope :voted_for, lambda { |votee| where(:_id => { '$in' => votee.voter_ids }) }
11
+ end
12
+
5
13
  module InstanceMethods
6
14
  # Check to see if this voter voted on the votee or not
7
15
  #
@@ -5,4 +5,6 @@ class Category
5
5
  field :name
6
6
 
7
7
  has_and_belongs_to_many :posts
8
+
9
+ voteable self, :index => true
8
10
  end
@@ -8,6 +8,6 @@ class Post
8
8
  has_and_belongs_to_many :categories
9
9
  has_many :comments
10
10
 
11
- voteable self, :up => +1, :down => -1
11
+ voteable self, :up => +1, :down => -1, :index => true
12
12
  voteable Category, :up => +3, :down => -5, :update_counters => false
13
13
  end
@@ -1,6 +1,35 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Mongoid::Voteable do
4
+
5
+ context 'when :index is passed as an argument' do
6
+ before do
7
+ Post.collection.drop_indexes
8
+ Category.collection.drop_indexes
9
+ end
10
+
11
+ it 'defines indexes' do
12
+ [Post, Category].each do |klass|
13
+ klass.create_indexes
14
+ [ 'votes.up_1__id_1',
15
+ 'votes.down_1__id_1'
16
+ ].each { |index_key|
17
+ klass.collection.index_information.should have_key index_key
18
+ klass.collection.index_information[index_key]['unique'].should be_true
19
+ klass.collection.index_information[index_key]['background'].should be_true
20
+ }
21
+
22
+ [ 'votes.count_-1',
23
+ 'votes.up_count_-1',
24
+ 'votes.down_count_-1',
25
+ 'votes.point_-1'
26
+ ].each { |index_key|
27
+ klass.collection.index_information.should have_key index_key
28
+ }
29
+ end
30
+ end
31
+ end
32
+
4
33
  before :all do
5
34
  @category1 = Category.create!(:name => 'xyz')
6
35
  @category2 = Category.create!(:name => 'abc')
@@ -123,6 +152,10 @@ describe Mongoid::Voteable do
123
152
  @post1.vote_value(@user2.id).should be_nil
124
153
  @post1.should_not be_voted_by(@user2.id)
125
154
 
155
+ @post1.up_voters(User).should == [ @user1 ]
156
+ @post1.voters(User).should == [ @user1 ]
157
+ @post1.down_voters(User).should be_empty
158
+
126
159
  Post.voted_by(@user1).to_a.should == [ @post1 ]
127
160
  Post.voted_by(@user2).to_a.should be_empty
128
161
 
@@ -173,6 +206,12 @@ describe Mongoid::Voteable do
173
206
  @post1.vote_value(@user2.id).should == :down
174
207
  end
175
208
 
209
+ it 'post1 get voters' do
210
+ @post1.up_voters(User).should == [ @user1 ]
211
+ @post1.down_voters(User).should == [ @user2 ]
212
+ @post1.voters(User).should == [ @user1, @user2 ]
213
+ end
214
+
176
215
  it 'posts voted_by user1, user2 is post1 only' do
177
216
  Post.voted_by(@user1).to_a.should == [ @post1 ]
178
217
  Post.voted_by(@user2).to_a.should == [ @post1 ]
@@ -248,7 +287,7 @@ describe Mongoid::Voteable do
248
287
  @post2.vote_value(@user1.id).should == :up
249
288
  @post2.vote_value(@user2.id).should be_nil
250
289
 
251
- Post.voted_by(@user1).to_a.should == [ @post1, @post2 ]
290
+ Post.voted_by(@user1).sort.should == [ @post1, @post2 ].sort
252
291
  end
253
292
  end
254
293
 
@@ -53,6 +53,10 @@ describe Mongoid::Voter do
53
53
  Post.up_voted_by(@user1).to_a.should == [ @post1 ]
54
54
  Post.down_voted_by(@user1).to_a.should be_empty
55
55
  Post.voted_by(@user2).to_a.should be_empty
56
+
57
+ User.up_voted_for(@post1).should == [ @user1 ]
58
+ User.down_voted_for(@post1).should be_empty
59
+ User.voted_for(@post1).should == [ @user1 ]
56
60
  end
57
61
 
58
62
  it 'user1 vote post1 has no effect' do
@@ -83,6 +87,10 @@ describe Mongoid::Voter do
83
87
  Post.voted_by(@user2).to_a.should == [ @post1 ]
84
88
  Post.up_voted_by(@user2).to_a.should be_empty
85
89
  Post.down_voted_by(@user2).to_a.should == [ @post1 ]
90
+
91
+ User.up_voted_for(@post1).should == [ @user1 ]
92
+ User.down_voted_for(@post1).should == [ @user2 ]
93
+ User.voted_for(@post1).should == [ @user1, @user2 ]
86
94
  end
87
95
  end
88
96
 
@@ -134,7 +142,7 @@ describe Mongoid::Voter do
134
142
  @user1.vote_value(@post2).should == :up
135
143
  @user2.vote_value(@post2).should be_nil
136
144
 
137
- Post.voted_by(@user1).to_a.should == [ @post1, @post2 ]
145
+ Post.voted_by(@user1).sort.should == [ @post1, @post2 ].sort
138
146
  end
139
147
  end
140
148
  end
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.3
5
+ version: 0.7.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Nguyen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-24 00:00:00 Z
13
+ date: 2011-05-02 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mongoid