rs_voteable_mongo 1.0.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.
@@ -0,0 +1,436 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Mongo::Voteable do
4
+
5
+ context 'when :index is passed as an argument' do
6
+ before do
7
+ Post.remove_indexes
8
+ Category.remove_indexes
9
+
10
+ Post.create_voteable_indexes
11
+ Category.create_voteable_indexes
12
+ end
13
+
14
+ it 'defines indexes' do
15
+ [Post, Category].each do |klass|
16
+ [ {'votes.up' => 1, '_id' => 1},
17
+ {'votes.down' => 1, '_id' => 1},
18
+ ].each { |index_key|
19
+ klass.collection.indexes[index_key].should_not be_nil
20
+ klass.collection.indexes[index_key]['unique'].should be_true
21
+ }
22
+
23
+ [ {'votes.count' => -1},
24
+ {'votes.up_count' => -1},
25
+ {'votes.down_count' => -1},
26
+ {'votes.point' => -1},
27
+ ].each { |index_key|
28
+ klass.collection.indexes[index_key].should_not be_nil
29
+ }
30
+ end
31
+ end
32
+ end
33
+
34
+ before :all do
35
+ Category.destroy_all
36
+ @category1 = Category.create!(:name => 'xyz')
37
+ @category2 = Category.create!(:name => 'abc')
38
+ Post.destroy_all
39
+ @post1 = Post.create!(:title => 'post1')
40
+ @post2 = Post.create!(:title => 'post2')
41
+
42
+ @post1.category_ids = [@category1.id, @category2.id]
43
+ @post1.save!
44
+
45
+ @comment = @post2.comments.create!
46
+
47
+ @user1 = User.create!
48
+ @user2 = User.create!
49
+ end
50
+
51
+ it "vote for unexisting post" do
52
+ object_id = defined?(Moped::BSON) ? Moped::BSON::ObjectId : BSON::ObjectId
53
+ @user1.vote(:votee_class => Post, :votee_id => object_id.new, :value => :up).should == false
54
+ end
55
+
56
+ context "just created" do
57
+ it 'votes_count, up_votes_count, down_votes_count, votes_point should be zero' do
58
+ @category1.up_votes_count.should == 0
59
+ @category1.down_votes_count.should == 0
60
+ @category1.votes_count.should == 0
61
+ @category1.votes_point.should == 0
62
+
63
+ @category2.up_votes_count.should == 0
64
+ @category2.down_votes_count.should == 0
65
+ @category2.votes_count.should == 0
66
+ @category2.votes_point.should == 0
67
+
68
+ @post1.up_votes_count.should == 0
69
+ @post1.down_votes_count.should == 0
70
+ @post1.votes_count.should == 0
71
+ @post1.votes_point.should == 0
72
+
73
+ @post2.up_votes_count.should == 0
74
+ @post2.down_votes_count.should == 0
75
+ @post2.votes_count.should == 0
76
+ @post2.votes_point.should == 0
77
+
78
+ @comment.up_votes_count.should == 0
79
+ @comment.down_votes_count.should == 0
80
+ @comment.votes_count.should == 0
81
+ @comment.votes_point.should == 0
82
+ end
83
+
84
+ it 'up_voter_ids, down_voter_ids should be empty' do
85
+ @category1.up_voter_ids.should be_empty
86
+ @category1.down_voter_ids.should be_empty
87
+
88
+ @category2.up_voter_ids.should be_empty
89
+ @category2.down_voter_ids.should be_empty
90
+
91
+ @post1.up_voter_ids.should be_empty
92
+ @post1.down_voter_ids.should be_empty
93
+
94
+ @post2.up_voter_ids.should be_empty
95
+ @post2.down_voter_ids.should be_empty
96
+
97
+ @comment.up_voter_ids.should be_empty
98
+ @comment.down_voter_ids.should be_empty
99
+ end
100
+
101
+ it 'voted by voter should be empty' do
102
+ Category.voted_by(@user1).should be_empty
103
+ Category.voted_by(@user2).should be_empty
104
+
105
+ Post.voted_by(@user1).should be_empty
106
+ Post.voted_by(@user2).should be_empty
107
+
108
+ Comment.voted_by(@user1).should be_empty
109
+ Comment.voted_by(@user2).should be_empty
110
+ end
111
+
112
+ it 'revote post1 has no effect' do
113
+ @post1.vote(:revote => true, :voter => @user1, :value => 'up')
114
+
115
+ @post1.up_votes_count.should == 0
116
+ @post1.down_votes_count.should == 0
117
+ @post1.votes_count.should == 0
118
+ @post1.votes_point.should == 0
119
+ end
120
+
121
+ it 'revote post2 has no effect' do
122
+ Post.vote(:revote => true, :votee_id => @post2.id, :voter_id => @user2.id, :value => :down)
123
+ @post2.reload
124
+
125
+ @post2.up_votes_count.should == 0
126
+ @post2.down_votes_count.should == 0
127
+ @post2.votes_count.should == 0
128
+ @post2.votes_point.should == 0
129
+ end
130
+ end
131
+
132
+ context 'user1 vote up post1 the first time' do
133
+ before :all do
134
+ @post = @post1.vote(:voter_id => @user1.id, :value => :up)
135
+ end
136
+
137
+ it 'validates return post' do
138
+ @post.should be_is_a Post
139
+ @post.should_not be_new_record
140
+
141
+ @post.votes.should == {
142
+ 'up' => [@user1.id],
143
+ 'down' => [],
144
+ 'up_count' => 1,
145
+ 'down_count' => 0,
146
+ 'count' => 1,
147
+ 'point' => 1
148
+ }
149
+ end
150
+
151
+ it 'validates' do
152
+ @post1.up_votes_count.should == 1
153
+ @post1.down_votes_count.should == 0
154
+ @post1.votes_count.should == 1
155
+ @post1.votes_point.should == 1
156
+
157
+ @post1.vote_value(@user1).should == :up
158
+ @post1.should be_voted_by(@user1)
159
+ @post1.vote_value(@user2.id).should be_nil
160
+ @post1.should_not be_voted_by(@user2.id)
161
+
162
+ @post1.up_voters(User).to_a.should == [ @user1 ]
163
+ @post1.voters(User).to_a.should == [ @user1 ]
164
+ @post1.down_voters(User).should be_empty
165
+
166
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
167
+ Post.voted_by(@user2).to_a.should be_empty
168
+
169
+ @category1.reload
170
+ @category1.up_votes_count.should == 0
171
+ @category1.down_votes_count.should == 0
172
+ @category1.votes_count.should == 0
173
+ @category1.votes_point.should == 3
174
+
175
+ @category2.reload
176
+ @category2.up_votes_count.should == 0
177
+ @category2.down_votes_count.should == 0
178
+ @category2.votes_count.should == 0
179
+ @category2.votes_point.should == 3
180
+ end
181
+
182
+ it 'user1 vote post1 has no effect' do
183
+ Post.vote(:revote => false, :votee_id => @post1.id, :voter_id => @user1.id, :value => :up)
184
+ @post1.reload
185
+
186
+ @post1.up_votes_count.should == 1
187
+ @post1.down_votes_count.should == 0
188
+ @post1.votes_count.should == 1
189
+ @post1.votes_point.should == 1
190
+
191
+ @post1.vote_value(@user1.id).should == :up
192
+ end
193
+ end
194
+
195
+ context 'user2 vote down post1 the first time' do
196
+ before :all do
197
+ Post.vote(:votee_id => @post1.id, :voter_id => @user2.id, :value => :down)
198
+ @post1.reload
199
+ end
200
+
201
+ it 'post1 up_votes_count is the same' do
202
+ @post1.up_votes_count.should == 1
203
+ end
204
+
205
+ it 'post1 vote_value on user1 is the same' do
206
+ @post1.vote_value(@user1.id).should == :up
207
+ end
208
+
209
+ it 'down_votes_count, votes_count, and votes_point changed' do
210
+ @post1.down_votes_count.should == 1
211
+ @post1.votes_count.should == 2
212
+ @post1.votes_point.should == 0
213
+ @post1.vote_value(@user2.id).should == :down
214
+ end
215
+
216
+ it 'post1 get voters' do
217
+ @post1.up_voters(User).to_a.should == [ @user1 ]
218
+ @post1.down_voters(User).to_a.should == [ @user2 ]
219
+ @post1.voters(User).to_a.should == [ @user1, @user2 ]
220
+ end
221
+
222
+ it 'posts voted_by user1, user2 is post1 only' do
223
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
224
+ Post.voted_by(@user2).to_a.should == [ @post1 ]
225
+ end
226
+
227
+ it 'categories votes' do
228
+ @category1.reload
229
+ @category1.up_votes_count.should == 0
230
+ @category1.down_votes_count.should == 0
231
+ @category1.votes_count.should == 0
232
+ @category1.votes_point.should == -2
233
+
234
+ @category2.reload
235
+ @category2.up_votes_count.should == 0
236
+ @category2.down_votes_count.should == 0
237
+ @category2.votes_count.should == 0
238
+ @category2.votes_point.should == -2
239
+ end
240
+ end
241
+
242
+ context 'user1 change vote on post1 from up to down' do
243
+ before :all do
244
+ Post.vote(:revote => true, :votee_id => @post1.id, :voter_id => @user1.id, :value => :down)
245
+ Mongo::Voteable::Tasks.remake_stats
246
+ @post1.reload
247
+ end
248
+
249
+ it 'validates' do
250
+ @post1.up_votes_count.should == 0
251
+ @post1.down_votes_count.should == 2
252
+ @post1.votes_count.should == 2
253
+ @post1.votes_point.should == -2
254
+
255
+ @post1.vote_value(@user1.id).should == :down
256
+ @post1.vote_value(@user2.id).should == :down
257
+
258
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
259
+ Post.voted_by(@user2).to_a.should == [ @post1 ]
260
+ end
261
+ end
262
+
263
+ context 'user1 vote down post2 the first time' do
264
+ before :all do
265
+ @post2.vote(:voter_id => @user1.id, :value => :down)
266
+ end
267
+
268
+ it 'validates' do
269
+ @post2.up_votes_count.should == 0
270
+ @post2.down_votes_count.should == 1
271
+ @post2.votes_count.should == 1
272
+ @post2.votes_point.should == -1
273
+
274
+ @post2.vote_value(@user1.id).should == :down
275
+ @post2.vote_value(@user2.id).should be_nil
276
+
277
+ Post.voted_by(@user1).to_a.should == [ @post1, @post2 ]
278
+ end
279
+ end
280
+
281
+ context 'user1 change vote on post2 from down to up' do
282
+ before :all do
283
+ Post.vote(:revote => true, :votee_id => @post2.id.to_s, :voter_id => @user1.id.to_s, :value => :up)
284
+ Mongo::Voteable::Tasks.remake_stats
285
+ @post2.reload
286
+ end
287
+
288
+ it 'validates' do
289
+ @post2.up_votes_count.should == 1
290
+ @post2.down_votes_count.should == 0
291
+ @post2.votes_count.should == 1
292
+ @post2.votes_point.should == 1
293
+
294
+ @post2.vote_value(@user1.id).should == :up
295
+ @post2.vote_value(@user2.id).should be_nil
296
+
297
+ Post.voted_by(@user1).size.should == 2
298
+ Post.voted_by(@user1).should be_include @post1
299
+ Post.voted_by(@user1).should be_include @post2
300
+ end
301
+ end
302
+
303
+
304
+ context 'user1 vote up post2 comment the first time' do
305
+ before :all do
306
+ @comment.vote(:voter_id => @user1.id, :value => :up)
307
+ @comment.reload
308
+ @post2.reload
309
+ end
310
+
311
+ it 'validates' do
312
+ @post2.up_votes_count.should == 2
313
+ @post2.down_votes_count.should == 0
314
+ @post2.votes_count.should == 2
315
+ @post2.votes_point.should == 3
316
+
317
+ @comment.up_votes_count.should == 1
318
+ @comment.down_votes_count.should == 0
319
+ @comment.votes_count.should == 1
320
+ @comment.votes_point.should == 1
321
+ end
322
+ end
323
+
324
+
325
+ context 'user1 revote post2 comment from up to down' do
326
+ before :all do
327
+ @user1.vote(:votee => @comment, :value => :down)
328
+ @comment.reload
329
+ @post2.reload
330
+ end
331
+
332
+ it 'validates' do
333
+ @post2.up_votes_count.should == 1
334
+ @post2.down_votes_count.should == 1
335
+ @post2.votes_count.should == 2
336
+ @post2.votes_point.should == 0
337
+
338
+ @comment.up_votes_count.should == 0
339
+ @comment.down_votes_count.should == 1
340
+ @comment.votes_count.should == 1
341
+ @comment.votes_point.should == -3
342
+ end
343
+
344
+ it 'revote with wrong value has no effect' do
345
+ @user1.vote(:votee => @comment, :value => :down)
346
+
347
+ @post2.up_votes_count.should == 1
348
+ @post2.down_votes_count.should == 1
349
+ @post2.votes_count.should == 2
350
+ @post2.votes_point.should == 0
351
+
352
+ @comment.up_votes_count.should == 0
353
+ @comment.down_votes_count.should == 1
354
+ @comment.votes_count.should == 1
355
+ @comment.votes_point.should == -3
356
+ end
357
+ end
358
+
359
+ context "user1 unvote on post1" do
360
+ before(:all) do
361
+ @post1.vote(:voter_id => @user1.id, :votee_id => @post1.id, :unvote => true)
362
+ Mongo::Voteable::Tasks.remake_stats
363
+ @post1.reload
364
+ end
365
+
366
+ it 'validates' do
367
+ @post1.up_votes_count.should == 0
368
+ @post1.down_votes_count.should == 1
369
+ @post1.votes_count.should == 1
370
+ @post1.votes_point.should == -1
371
+
372
+ @post1.vote_value(@user1.id).should be_nil
373
+ @post1.vote_value(@user2.id).should == :down
374
+
375
+ Post.voted_by(@user1).to_a.should_not include(@post1)
376
+ end
377
+ end
378
+
379
+ context "@post1 has 1 down vote and -1 point, @post2 has 1 up vote, 1 down vote and 0 point" do
380
+ it "verify @post1 counters" do
381
+ @post1.up_votes_count.should == 0
382
+ @post1.down_votes_count.should == 1
383
+ @post1.votes_count.should == 1
384
+ @post1.votes_point.should == -1
385
+ end
386
+
387
+ it "verify @post2 counters" do
388
+ @post2.up_votes_count.should == 1
389
+ @post2.down_votes_count.should == 1
390
+ @post2.votes_count.should == 2
391
+ @post2.votes_point.should == 0
392
+ end
393
+ end
394
+
395
+ context "user1 unvote on comment" do
396
+ before(:all) do
397
+ @user1.unvote(@comment)
398
+ Mongo::Voteable::Tasks.remake_stats
399
+ @comment.reload
400
+ @post2.reload
401
+ end
402
+
403
+ it "" do
404
+ @comment.up_votes_count.should == 0
405
+ @comment.down_votes_count.should == 0
406
+ @comment.votes_count.should == 0
407
+ @comment.votes_point.should == 0
408
+
409
+ @post2.up_votes_count.should == 1
410
+ @post2.down_votes_count.should == 0
411
+ @post2.votes_count.should == 1
412
+ @post2.votes_point.should == 1
413
+ end
414
+ end
415
+
416
+ context 'final' do
417
+ it "test remake stats" do
418
+ Mongo::Voteable::Tasks.remake_stats
419
+
420
+ @post1.up_votes_count.should == 0
421
+ @post1.down_votes_count.should == 1
422
+ @post1.votes_count.should == 1
423
+ @post1.votes_point.should == -1
424
+
425
+ @post2.up_votes_count.should == 1
426
+ @post2.down_votes_count.should == 0
427
+ @post2.votes_count.should == 1
428
+ @post2.votes_point.should == 1
429
+
430
+ @comment.up_votes_count.should == 0
431
+ @comment.down_votes_count.should == 0
432
+ @comment.votes_count.should == 0
433
+ @comment.votes_point.should == 0
434
+ end
435
+ end
436
+ end
@@ -0,0 +1,150 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Mongo::Voter do
4
+ before :all do
5
+ @post1 = Post.create!(:title => 'post_1')
6
+ @post2 = Post.create!(:title => 'post_2')
7
+
8
+ @user1 = User.create!
9
+ @user2 = User.create!
10
+ end
11
+
12
+ context "just created" do
13
+ it 'validates' do
14
+ Post.voted_by(@user1).should be_empty
15
+ Post.up_voted_by(@user1).should be_empty
16
+ Post.down_voted_by(@user1).should be_empty
17
+ @user1.voted?(@post1).should be_false
18
+ @user1.voted?(@post2).should be_false
19
+
20
+ Post.voted_by(@user2).should be_empty
21
+ Post.up_voted_by(@user2).should be_empty
22
+ Post.down_voted_by(@user2).should be_empty
23
+ @user2.voted?(@post1).should be_false
24
+ @user2.voted?(@post2).should be_false
25
+ end
26
+
27
+ it 'revote has no effect' do
28
+ @user2.vote(:revote => true, :votee => @post2, :value => :down)
29
+ @post2.reload
30
+
31
+ @post2.votes_count.should == 0
32
+ @post2.votes_point.should == 0
33
+ end
34
+ end
35
+
36
+ context 'user1 vote up post1 the first time' do
37
+ before :all do
38
+ @user1.vote(:revote => '', :votee_id => @post1.id, :votee_class => Post, :value => :up)
39
+ @post1.reload
40
+ end
41
+
42
+ it 'validates' do
43
+ @post1.votes_count.should == 1
44
+ @post1.votes_point.should == 1
45
+
46
+ @user1.vote_value(@post1).should == :up
47
+ @user2.vote_value(:votee_class => Post, :votee_id => @post1.id).should be_nil
48
+
49
+ @user1.should be_voted(@post1)
50
+ @user2.should_not be_voted(:votee_class => Post, :votee_id => @post1.id)
51
+
52
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
53
+ Post.up_voted_by(@user1).to_a.should == [ @post1 ]
54
+ Post.down_voted_by(@user1).to_a.should be_empty
55
+ Post.voted_by(@user2).to_a.should be_empty
56
+
57
+ User.up_voted_for(@post1).to_a.should == [ @user1 ]
58
+ User.down_voted_for(@post1).to_a.should be_empty
59
+ User.voted_for(@post1).to_a.should == [ @user1 ]
60
+ end
61
+
62
+ it 'user1 vote post1 has no effect' do
63
+ @user1.vote(:votee => @post1, :value => :up)
64
+ @post1.reload
65
+
66
+ @post1.votes_count.should == 1
67
+ @post1.votes_point.should == 1
68
+
69
+ @post1.vote_value(@user1.id).should == :up
70
+ end
71
+ end
72
+
73
+ context 'user2 vote down post1 the first time' do
74
+ before :all do
75
+ @user2.vote(:votee => @post1, :value => :down)
76
+ @post1.reload
77
+ end
78
+
79
+ it 'validates' do
80
+ @post1.votes_count.should == 2
81
+ @post1.votes_point.should == 0
82
+
83
+ @user1.vote_value(@post1).should == :up
84
+ @user2.vote_value(@post1).should == :down
85
+
86
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
87
+ Post.voted_by(@user2).to_a.should == [ @post1 ]
88
+ Post.up_voted_by(@user2).to_a.should be_empty
89
+ Post.down_voted_by(@user2).to_a.should == [ @post1 ]
90
+
91
+ User.up_voted_for(@post1).to_a.should == [ @user1 ]
92
+ User.down_voted_for(@post1).to_a.should == [ @user2 ]
93
+ User.voted_for(@post1).to_a.should == [ @user1, @user2 ]
94
+ end
95
+ end
96
+
97
+ context 'user1 change vote on post1 from up to down' do
98
+ before :all do
99
+ @user1.vote(:votee => @post1, :value => :down)
100
+ @post1.reload
101
+ end
102
+
103
+ it 'validates' do
104
+ @post1.votes_count.should == 2
105
+ @post1.votes_point.should == -2
106
+
107
+ @user1.vote_value(@post1).should == :down
108
+ @user2.vote_value(@post1).should == :down
109
+
110
+ Post.voted_by(@user1).to_a.should == [ @post1 ]
111
+ Post.voted_by(@user2).to_a.should == [ @post1 ]
112
+ end
113
+ end
114
+
115
+ context 'user1 vote down post2 the first time' do
116
+ before :all do
117
+ @user1.vote(:new => 'abc', :votee => @post2, :value => :down)
118
+ @post2.reload
119
+ end
120
+
121
+ it 'validates' do
122
+ @post2.votes_count.should == 1
123
+ @post2.votes_point.should == -1
124
+
125
+ @user1.vote_value(@post2).should == :down
126
+ @user2.vote_value(@post2).should be_nil
127
+
128
+ Post.voted_by(@user1).to_a.should == [ @post1, @post2 ]
129
+ end
130
+ end
131
+
132
+ context 'user1 change vote on post2 from down to up' do
133
+ before :all do
134
+ @user1.vote(:revote => 'abc', :votee => @post2, :value => :up)
135
+ @post2.reload
136
+ end
137
+
138
+ it 'validates' do
139
+ @post2.votes_count.should == 1
140
+ @post2.votes_point.should == 1
141
+
142
+ @user1.vote_value(@post2).should == :up
143
+ @user2.vote_value(@post2).should be_nil
144
+
145
+ Post.voted_by(@user1).size.should == 2
146
+ Post.voted_by(@user1).should be_include @post1
147
+ Post.voted_by(@user1).should be_include @post2
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'voteable_mongo/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rs_voteable_mongo'
7
+ s.version = VoteableMongo::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['RocketScience','Alex Nguyen']
10
+ s.email = ['i@gleb.tv','alex@vinova.sg']
11
+ s.homepage = 'https://github.com/rs-pro/voteable_mongo'
12
+ s.summary = %q{Add up / down voting ability to Mongoid documents}
13
+ s.description = %q{Add up / down voting ability to Mongoid documents. Optimized for speed by using only ONE request to MongoDB to validate, update, and retrieve updated data.}
14
+
15
+ s.add_dependency "mongoid", [">= 3.0", "< 5.0"]
16
+ s.add_development_dependency 'rspec', '~> 2.14.1'
17
+
18
+ s.rubyforge_project = 'voteable_mongo'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ['lib']
24
+ end