mongo_mapper 0.13.1 → 0.14.0.rc1

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.
Files changed (103) hide show
  1. checksums.yaml +13 -5
  2. data/README.rdoc +3 -6
  3. data/lib/mongo_mapper.rb +1 -0
  4. data/lib/mongo_mapper/document.rb +2 -0
  5. data/lib/mongo_mapper/extensions/array.rb +14 -6
  6. data/lib/mongo_mapper/extensions/hash.rb +15 -3
  7. data/lib/mongo_mapper/extensions/object.rb +4 -0
  8. data/lib/mongo_mapper/extensions/string.rb +13 -5
  9. data/lib/mongo_mapper/plugins/accessible.rb +12 -11
  10. data/lib/mongo_mapper/plugins/associations.rb +7 -6
  11. data/lib/mongo_mapper/plugins/associations/base.rb +13 -12
  12. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +9 -8
  13. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +12 -11
  14. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +4 -4
  15. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +24 -23
  16. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +18 -16
  17. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +55 -48
  18. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +14 -13
  19. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +7 -6
  20. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +7 -5
  21. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +14 -11
  22. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +14 -13
  23. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +9 -9
  24. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +27 -26
  25. data/lib/mongo_mapper/plugins/associations/proxy.rb +29 -26
  26. data/lib/mongo_mapper/plugins/callbacks.rb +13 -0
  27. data/lib/mongo_mapper/plugins/counter_cache.rb +23 -4
  28. data/lib/mongo_mapper/plugins/dirty.rb +2 -2
  29. data/lib/mongo_mapper/plugins/dynamic_querying.rb +10 -9
  30. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +17 -16
  31. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -1
  32. data/lib/mongo_mapper/plugins/identity_map.rb +1 -1
  33. data/lib/mongo_mapper/plugins/indexes.rb +1 -1
  34. data/lib/mongo_mapper/plugins/keys.rb +158 -158
  35. data/lib/mongo_mapper/plugins/keys/key.rb +16 -10
  36. data/lib/mongo_mapper/plugins/keys/static.rb +45 -0
  37. data/lib/mongo_mapper/plugins/modifiers.rb +27 -26
  38. data/lib/mongo_mapper/plugins/partial_updates.rb +86 -0
  39. data/lib/mongo_mapper/plugins/persistence.rb +7 -6
  40. data/lib/mongo_mapper/plugins/protected.rb +6 -5
  41. data/lib/mongo_mapper/plugins/querying.rb +80 -43
  42. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +14 -9
  43. data/lib/mongo_mapper/plugins/scopes.rb +78 -7
  44. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  45. data/lib/mongo_mapper/plugins/validations.rb +0 -0
  46. data/lib/mongo_mapper/version.rb +1 -1
  47. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +12 -13
  48. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +9 -9
  49. data/spec/functional/accessible_spec.rb +12 -12
  50. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +11 -11
  51. data/spec/functional/associations/belongs_to_proxy_spec.rb +14 -15
  52. data/spec/functional/associations/in_array_proxy_spec.rb +6 -6
  53. data/spec/functional/associations/many_documents_proxy_spec.rb +89 -18
  54. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +11 -11
  55. data/spec/functional/associations/many_embedded_proxy_spec.rb +1 -1
  56. data/spec/functional/associations/one_as_proxy_spec.rb +14 -14
  57. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +9 -9
  58. data/spec/functional/associations/one_embedded_proxy_spec.rb +3 -3
  59. data/spec/functional/associations/one_proxy_spec.rb +14 -14
  60. data/spec/functional/caching_spec.rb +8 -8
  61. data/spec/functional/callbacks_spec.rb +87 -0
  62. data/spec/functional/counter_cache_spec.rb +89 -0
  63. data/spec/functional/dirty_spec.rb +41 -41
  64. data/spec/functional/document_spec.rb +3 -3
  65. data/spec/functional/embedded_document_spec.rb +18 -18
  66. data/spec/functional/identity_map_spec.rb +28 -15
  67. data/spec/functional/indexes_spec.rb +4 -4
  68. data/spec/functional/keys_spec.rb +12 -3
  69. data/spec/functional/logger_spec.rb +1 -1
  70. data/spec/functional/modifiers_spec.rb +2 -2
  71. data/spec/functional/partial_updates_spec.rb +577 -0
  72. data/spec/functional/protected_spec.rb +13 -13
  73. data/spec/functional/querying_spec.rb +11 -10
  74. data/spec/functional/safe_spec.rb +2 -2
  75. data/spec/functional/sci_spec.rb +3 -3
  76. data/spec/functional/scopes_spec.rb +234 -1
  77. data/spec/functional/static_keys_spec.rb +153 -0
  78. data/spec/functional/stats_spec.rb +0 -4
  79. data/spec/functional/touch_spec.rb +1 -1
  80. data/spec/functional/validations_spec.rb +59 -57
  81. data/spec/quality_spec.rb +1 -1
  82. data/spec/spec_helper.rb +7 -3
  83. data/spec/support/matchers.rb +4 -13
  84. data/spec/unit/associations/base_spec.rb +12 -12
  85. data/spec/unit/associations/belongs_to_association_spec.rb +2 -2
  86. data/spec/unit/associations/many_association_spec.rb +2 -2
  87. data/spec/unit/associations/one_association_spec.rb +2 -2
  88. data/spec/unit/associations/proxy_spec.rb +13 -15
  89. data/spec/unit/document_spec.rb +5 -5
  90. data/spec/unit/dynamic_finder_spec.rb +8 -8
  91. data/spec/unit/embedded_document_spec.rb +14 -14
  92. data/spec/unit/extensions_spec.rb +17 -17
  93. data/spec/unit/identity_map_middleware_spec.rb +5 -5
  94. data/spec/unit/key_spec.rb +24 -21
  95. data/spec/unit/keys_spec.rb +5 -5
  96. data/spec/unit/mongo_mapper_spec.rb +26 -26
  97. data/spec/unit/rails_spec.rb +2 -2
  98. data/spec/unit/serialization_spec.rb +1 -1
  99. data/spec/unit/time_zones_spec.rb +2 -2
  100. data/spec/unit/validations_spec.rb +28 -15
  101. metadata +16 -14
  102. data/lib/mongo_mapper/connections/10gen.rb +0 -0
  103. data/lib/mongo_mapper/connections/moped.rb +0 -0
@@ -44,12 +44,12 @@ describe 'A document with protected attributes' do
44
44
 
45
45
  it "should assign protected attribute through accessor" do
46
46
  @doc.admin = true
47
- @doc.admin.should be_true
47
+ @doc.admin.should be_truthy
48
48
  end
49
49
 
50
50
  it "should ignore protected attribute on #initialize" do
51
51
  doc = @doc_class.new(:name => 'John', :admin => true)
52
- doc.admin.should be_false
52
+ doc.admin.should be_falsey
53
53
  doc.name.should == 'John'
54
54
  end
55
55
 
@@ -59,7 +59,7 @@ describe 'A document with protected attributes' do
59
59
  doc.save!
60
60
 
61
61
  doc = @doc_class.first(:name => 'John')
62
- doc.admin.should be_true
62
+ doc.admin.should be_truthy
63
63
  doc.name.should == 'John'
64
64
  end
65
65
 
@@ -69,37 +69,37 @@ describe 'A document with protected attributes' do
69
69
  doc.save!
70
70
 
71
71
  doc.reload
72
- doc.admin.should be_true
72
+ doc.admin.should be_truthy
73
73
  doc.name.should == 'John'
74
74
  end
75
75
 
76
76
  it "should ignore protected attribute on #update_attribute" do
77
77
  @doc.update_attribute('admin', true)
78
- @doc.admin.should be_true
78
+ @doc.admin.should be_truthy
79
79
  end
80
80
 
81
81
  it "should ignore protected attribute on #update_attributes" do
82
82
  @doc.update_attributes(:name => 'Ren Hoek', :admin => true)
83
83
  @doc.name.should == 'Ren Hoek'
84
- @doc.admin.should be_false
84
+ @doc.admin.should be_falsey
85
85
  end
86
86
 
87
87
  it "should ignore protected attribute on #update_attributes!" do
88
88
  @doc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
89
89
  @doc.name.should == 'Stimpson J. Cat'
90
- @doc.admin.should be_false
90
+ @doc.admin.should be_falsey
91
91
  end
92
92
 
93
93
  it "should ignore protecteds attribute on #attributes=" do
94
94
  @doc.attributes = {:name => 'Stimpson J. Cat', :admin => true}
95
95
  @doc.name.should == 'Stimpson J. Cat'
96
- @doc.admin.should be_false
96
+ @doc.admin.should be_falsey
97
97
  end
98
98
 
99
99
  it "should be indifferent to whether the protected keys are strings or symbols" do
100
100
  @doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
101
101
  @doc.name.should == 'Stimpson J. Cat'
102
- @doc.admin.should be_false
102
+ @doc.admin.should be_falsey
103
103
  end
104
104
 
105
105
  it "should accept nil as constructor's argument without raising exception" do
@@ -177,23 +177,23 @@ describe 'An embedded document with protected attributes' do
177
177
 
178
178
  it "should assign protected attribute through accessor" do
179
179
  @edoc.admin = true
180
- @edoc.admin.should be_true
180
+ @edoc.admin.should be_truthy
181
181
  end
182
182
 
183
183
  it "should not ignore protected attribute on #update_attribute" do
184
184
  @edoc.update_attribute('admin', true)
185
- @edoc.admin.should be_true
185
+ @edoc.admin.should be_truthy
186
186
  end
187
187
 
188
188
  it "should ignore protected attribute on #update_attributes" do
189
189
  @edoc.update_attributes(:name => 'Ren Hoek', :admin => true)
190
190
  @edoc.name.should == 'Ren Hoek'
191
- @edoc.admin.should be_false
191
+ @edoc.admin.should be_falsey
192
192
  end
193
193
 
194
194
  it "should ignore protected attribute on #update_attributes!" do
195
195
  @edoc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
196
196
  @edoc.name.should == 'Stimpson J. Cat'
197
- @edoc.admin.should be_false
197
+ @edoc.admin.should be_falsey
198
198
  end
199
199
  end
@@ -55,7 +55,7 @@ describe "Querying" do
55
55
  end
56
56
 
57
57
  it "should no longer be new?" do
58
- doc.new?.should be_false
58
+ doc.new?.should be_falsey
59
59
  end
60
60
 
61
61
  it "should return instance of document" do
@@ -495,12 +495,12 @@ describe "Querying" do
495
495
 
496
496
  context ".empty?" do
497
497
  it "should be true if no documents" do
498
- document.empty?.should be_true
498
+ document.empty?.should be_truthy
499
499
  end
500
500
 
501
501
  it "should be false if documents present" do
502
502
  @doc = document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
503
- document.empty?.should be_false
503
+ document.empty?.should be_falsey
504
504
  end
505
505
  end
506
506
 
@@ -737,11 +737,11 @@ describe "Querying" do
737
737
  end
738
738
 
739
739
  it "should be true if document valid" do
740
- document.new.update_attributes(:foo => 'bar').should be_true
740
+ document.new.update_attributes(:foo => 'bar').should be_truthy
741
741
  end
742
742
 
743
743
  it "should be false if document not valid" do
744
- document.new.update_attributes({}).should be_false
744
+ document.new.update_attributes({}).should be_falsey
745
745
  end
746
746
  end
747
747
 
@@ -751,20 +751,21 @@ describe "Querying" do
751
751
  end
752
752
 
753
753
  it "should accept symbols as keys" do
754
- @doc.update_attribute(:first_name, 'Chris').should be_true
754
+ @doc.update_attribute(:first_name, 'Chris').should be_truthy
755
755
  @doc.reload.first_name.should == 'Chris'
756
756
  end
757
757
 
758
758
  it "should update the attribute" do
759
- @doc.update_attribute('first_name', 'Chris').should be_true
759
+ @doc.update_attribute('first_name', 'Chris').should be_truthy
760
760
  @doc.reload.first_name.should == 'Chris'
761
761
  end
762
762
 
763
763
  it "should update the attribute without invoking validations" do
764
764
  document.key :name, String, :required => true
765
765
 
766
- @doc.should_receive(:valid?).never
767
- @doc.update_attribute('name', '').should be_true
766
+ expect(@doc).to receive(:valid?).never
767
+ @doc.update_attribute('name', '').should be_truthy
768
+
768
769
  @doc.reload.name.should == ''
769
770
  document.count.should == 1
770
771
  end
@@ -867,7 +868,7 @@ describe "Querying" do
867
868
 
868
869
  it "should insert invalid document" do
869
870
  doc = document.new
870
- doc.should_receive(:valid?).never
871
+ expect(doc).to receive(:valid?).never
871
872
  doc.save(:validate => false)
872
873
  document.count.should == 1
873
874
  end
@@ -67,7 +67,7 @@ describe "Safe" do
67
67
  context "using safe setting from class" do
68
68
  it "should pass :w => 1 option to save" do
69
69
  instance = @klass.new(:email => 'john@doe.com')
70
- Mongo::Collection.any_instance.should_receive(:insert).once.with({'_id' => instance.id, 'email' => 'john@doe.com'}, {:w => 1})
70
+ expect_any_instance_of(Mongo::Collection).to receive(:insert).once.with({'_id' => instance.id, 'email' => 'john@doe.com'}, {:w => 1})
71
71
  instance.save!
72
72
  end
73
73
 
@@ -122,7 +122,7 @@ describe "Safe" do
122
122
  context "using safe setting from class" do
123
123
  it "should pass :safe => options_hash to save" do
124
124
  instance = @klass.new(:email => 'john@doe.com')
125
- Mongo::Collection.any_instance.should_receive(:insert).once.with({'_id' => instance.id, 'email' => 'john@doe.com'}, {:j => true})
125
+ expect_any_instance_of(Mongo::Collection).to receive(:insert).once.with({'_id' => instance.id, 'email' => 'john@doe.com'}, {:j => true})
126
126
  instance.save!
127
127
  end
128
128
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe "Single collection inheritance (document)" do
4
4
  context "without a connection", :without_connection => true do
5
5
  it "should attempt to create a connection during inheritance" do
6
- Mongo::MongoClient.should_not_receive(:new)
6
+ expect(Mongo::MongoClient).to_not receive(:new)
7
7
  doc = Class.new
8
8
  doc.send(:include, MongoMapper::Document)
9
9
  expect {
@@ -49,7 +49,7 @@ describe "Single collection inheritance (document)" do
49
49
  end
50
50
 
51
51
  it "should automatically add _type key to store class" do
52
- DocParent.key?(:_type).should be_true
52
+ DocParent.key?(:_type).should be_truthy
53
53
  end
54
54
 
55
55
  it "should use modifiers properly" do
@@ -323,7 +323,7 @@ describe "Single collection inheritance (document)" do
323
323
  end
324
324
 
325
325
  it "should automatically add _type key" do
326
- Grandparent.key?(:_type).should be_true
326
+ Grandparent.key?(:_type).should be_truthy
327
327
  end
328
328
 
329
329
  context ".single_collection_inherited?" do
@@ -66,7 +66,7 @@ describe "Scopes" do
66
66
  @document.class_eval do
67
67
  scope :age, lambda { |age| {:age => age} }
68
68
  scope :ages, lambda { |low, high| {:age.gte => low, :age.lte => high} }
69
- scope :ordered, lambda { |sort| sort(sort) }
69
+ scope :ordered, lambda { |s| sort(s) }
70
70
  end
71
71
  end
72
72
 
@@ -201,4 +201,237 @@ describe "Scopes" do
201
201
  end
202
202
  end
203
203
  end
204
+
205
+ describe "with_scope" do
206
+ describe "with a base query" do
207
+ before do
208
+ @klass = Doc do
209
+ end
210
+ end
211
+
212
+ it "should scope" do
213
+ u1 = @klass.create!(:first_name => "Scott")
214
+ u2 = @klass.create!(:first_name => "Andrew")
215
+
216
+ run = false
217
+
218
+ @klass.with_scope(:first_name => "Scott") do
219
+ run = true
220
+ @klass.all.should == [u1]
221
+ end
222
+
223
+ run.should == true
224
+ end
225
+
226
+ it "should return the scope at the end of the block" do
227
+ u1 = @klass.create!(:first_name => "Scott")
228
+ u2 = @klass.create!(:first_name => "Andrew")
229
+
230
+ run = false
231
+
232
+ @klass.with_scope(:first_name => "Scott") do
233
+ run = true
234
+ @klass.all.should == [u1]
235
+ end
236
+
237
+ run.should == true
238
+
239
+ @klass.all.should include(u1)
240
+ @klass.all.should include(u2)
241
+ end
242
+
243
+ it "should be able to use an unscoped query" do
244
+ u1 = @klass.create!(:first_name => "Scott")
245
+ u2 = @klass.create!(:first_name => "Andrew")
246
+
247
+ run = false
248
+
249
+ @klass.with_scope(:first_name => "Scott") do
250
+ @klass.unscoped do
251
+ run = true
252
+ @klass.all.should include(u1)
253
+ @klass.all.should include(u2)
254
+ end
255
+
256
+ @klass.all.should == [u1]
257
+ end
258
+
259
+ run.should == true
260
+
261
+ @klass.all.should include(u1)
262
+ @klass.all.should include(u2)
263
+ end
264
+
265
+ it "should return the value of the block" do
266
+ u1 = @klass.create!(:first_name => "Scott")
267
+ u2 = @klass.create!(:first_name => "Andrew")
268
+
269
+ result = @klass.with_scope(:first_name => "Scott") do
270
+ @klass.all
271
+ end
272
+
273
+ result.should == [u1]
274
+ end
275
+
276
+ it "should have an empty list of default scope" do
277
+ @klass.default_scopes.should == []
278
+ end
279
+
280
+ it "should apply the default scope to all queries" do
281
+ @klass.key :active, Boolean, :default => true
282
+
283
+ normal = @klass.create!
284
+ inactive = @klass.create!(:active => false)
285
+
286
+ @klass.default_scope do
287
+ {
288
+ :active => true
289
+ }
290
+ end
291
+
292
+ @klass.all.should == [normal]
293
+ end
294
+
295
+ it "should allow multiple default scopes" do
296
+ @klass.key :active, Boolean, :default => true
297
+ @klass.key :soft_deleted, Boolean, :default => false
298
+
299
+ normal = @klass.create!
300
+ inactive = @klass.create!(:active => false)
301
+ deleted = @klass.create!(:soft_deleted => true)
302
+
303
+ @klass.default_scope do
304
+ {
305
+ :active => true,
306
+ }
307
+ end
308
+
309
+ @klass.default_scope do
310
+ {
311
+ :soft_deleted => false
312
+ }
313
+ end
314
+
315
+ @klass.all.should == [normal]
316
+ end
317
+
318
+ it "should allow a where inside a default_scope" do
319
+ @klass.key :active, Boolean, :default => true
320
+
321
+ normal = @klass.create!
322
+ inactive = @klass.create!(:active => false)
323
+
324
+ @klass.default_scope do
325
+ where(:active => true)
326
+ end
327
+
328
+ @klass.all.should == [normal]
329
+ end
330
+
331
+ it "should allow a hash directly" do
332
+ @klass.key :active, Boolean, :default => true
333
+
334
+ normal = @klass.create!
335
+ inactive = @klass.create!(:active => false)
336
+
337
+ @klass.default_scope :active => true
338
+
339
+ @klass.all.should == [normal]
340
+ end
341
+
342
+ it "should inherit default scopes, but only downwards" do
343
+ @klass.default_scope do
344
+ where(:active => true)
345
+ end
346
+ @subclass = Class.new(@klass)
347
+ @subclass.default_scopes.length.should == 1
348
+
349
+ @subclass.default_scope do
350
+ {
351
+ :foo => :bar
352
+ }
353
+ end
354
+
355
+ @subclass.default_scopes.length.should == 2
356
+ @klass.default_scopes.length.should == 1
357
+ end
358
+ end
359
+ end
360
+
361
+ describe "regression - multiple named scopes" do
362
+ it "should merge the hashes from multiple scopes" do
363
+ klass = Doc do
364
+ key :a, Boolean
365
+ key :b, Boolean
366
+ key :c, Boolean
367
+
368
+ scope :one, where(:a => true, :b => true)
369
+ scope :two, where(:c => true)
370
+ end
371
+
372
+ obj = klass.create!(:a => false, :b => true, :c => true)
373
+ klass.one.two.all.should == []
374
+
375
+ obj2 = klass.create(:a => true, :b => true, :c => true)
376
+ klass.one.two.all.should == [obj2]
377
+ end
378
+ end
379
+
380
+ describe "regression - with multiple scopes that set a key to nil" do
381
+ it "should still have the query as nil" do
382
+ klass = Doc do
383
+ key :a, Boolean
384
+
385
+ scope :one, lambda {
386
+ {
387
+ :a => nil
388
+ }
389
+ }
390
+ scope :two, lambda {
391
+ {
392
+ :a => nil
393
+ }
394
+ }
395
+ end
396
+
397
+ obj = klass.create!(:a => nil)
398
+ klass.one.two.all.should == [obj]
399
+ end
400
+ end
401
+
402
+ describe "regression - multiple scopes leading to empty query (array bug?)" do
403
+ before do
404
+ @klass = Doc do
405
+ key :send_at, Time
406
+
407
+ scope :unsent, lambda {
408
+ now = Time.now
409
+
410
+ {
411
+ send_at: {
412
+ '$lte' => now,
413
+ '$gte' => now - 30.days,
414
+ },
415
+ sent_at: nil,
416
+ }
417
+ }
418
+
419
+ scope :sorted, lambda {
420
+ sort(send_at: 1)
421
+ }
422
+ end
423
+ end
424
+
425
+ it "should filter properly by dates" do
426
+ old_obj = @klass.create(send_at: 3.months.ago)
427
+ one_day_ago = @klass.create(send_at: 1.day.ago)
428
+ two_days_ago = @klass.create(send_at: 2.days.ago)
429
+
430
+ all_unsorted = @klass.unsent.all
431
+
432
+ all_unsorted.should include(one_day_ago)
433
+ all_unsorted.should include(two_days_ago)
434
+ @klass.unsent.sorted.all.should == [two_days_ago, one_day_ago]
435
+ end
436
+ end
204
437
  end