mongo_mapper 0.14.0 → 0.15.4

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 (120) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +72 -0
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +19 -17
  10. data/lib/mongo_mapper/connection.rb +16 -38
  11. data/lib/mongo_mapper/extensions/array.rb +1 -1
  12. data/lib/mongo_mapper/extensions/binary.rb +1 -1
  13. data/lib/mongo_mapper/extensions/date.rb +1 -1
  14. data/lib/mongo_mapper/extensions/float.rb +1 -1
  15. data/lib/mongo_mapper/extensions/hash.rb +1 -1
  16. data/lib/mongo_mapper/extensions/nil_class.rb +2 -2
  17. data/lib/mongo_mapper/extensions/object.rb +1 -1
  18. data/lib/mongo_mapper/extensions/object_id.rb +6 -2
  19. data/lib/mongo_mapper/extensions/set.rb +1 -1
  20. data/lib/mongo_mapper/extensions/string.rb +1 -1
  21. data/lib/mongo_mapper/plugins/accessible.rb +1 -1
  22. data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
  23. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  24. data/lib/mongo_mapper/plugins/associations/many_association.rb +6 -5
  25. data/lib/mongo_mapper/plugins/associations/{belongs_to_polymorphic_proxy.rb → proxy/belongs_to_polymorphic_proxy.rb} +0 -0
  26. data/lib/mongo_mapper/plugins/associations/{belongs_to_proxy.rb → proxy/belongs_to_proxy.rb} +6 -0
  27. data/lib/mongo_mapper/plugins/associations/proxy/collection.rb +55 -0
  28. data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb} +0 -0
  29. data/lib/mongo_mapper/plugins/associations/{in_array_proxy.rb → proxy/in_array_proxy.rb} +36 -6
  30. data/lib/mongo_mapper/plugins/associations/proxy/in_foreign_array_proxy.rb +136 -0
  31. data/lib/mongo_mapper/plugins/associations/{many_documents_as_proxy.rb → proxy/many_documents_as_proxy.rb} +0 -0
  32. data/lib/mongo_mapper/plugins/associations/{many_documents_proxy.rb → proxy/many_documents_proxy.rb} +0 -4
  33. data/lib/mongo_mapper/plugins/associations/{many_embedded_polymorphic_proxy.rb → proxy/many_embedded_polymorphic_proxy.rb} +0 -0
  34. data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb} +0 -0
  35. data/lib/mongo_mapper/plugins/associations/{many_polymorphic_proxy.rb → proxy/many_polymorphic_proxy.rb} +0 -0
  36. data/lib/mongo_mapper/plugins/associations/{one_as_proxy.rb → proxy/one_as_proxy.rb} +0 -0
  37. data/lib/mongo_mapper/plugins/associations/{one_embedded_polymorphic_proxy.rb → proxy/one_embedded_polymorphic_proxy.rb} +0 -0
  38. data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb} +3 -1
  39. data/lib/mongo_mapper/plugins/associations/{one_proxy.rb → proxy/one_proxy.rb} +0 -0
  40. data/lib/mongo_mapper/plugins/associations/proxy/proxy.rb +164 -0
  41. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -13
  42. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  43. data/lib/mongo_mapper/plugins/document.rb +1 -1
  44. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
  45. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
  46. data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
  47. data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
  48. data/lib/mongo_mapper/plugins/indexes.rb +13 -6
  49. data/lib/mongo_mapper/plugins/keys.rb +12 -7
  50. data/lib/mongo_mapper/plugins/keys/key.rb +21 -13
  51. data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
  52. data/lib/mongo_mapper/plugins/persistence.rb +6 -2
  53. data/lib/mongo_mapper/plugins/querying.rb +9 -3
  54. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
  55. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  56. data/lib/mongo_mapper/plugins/scopes.rb +19 -3
  57. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  58. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  59. data/lib/mongo_mapper/plugins/validations.rb +1 -1
  60. data/lib/mongo_mapper/railtie.rb +1 -0
  61. data/lib/mongo_mapper/utils.rb +2 -2
  62. data/lib/mongo_mapper/version.rb +1 -1
  63. data/spec/examples.txt +1731 -0
  64. data/spec/functional/accessible_spec.rb +7 -1
  65. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
  66. data/spec/functional/associations/belongs_to_proxy_spec.rb +55 -5
  67. data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
  68. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  69. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  70. data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
  71. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
  72. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  73. data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
  74. data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
  75. data/spec/functional/associations/one_proxy_spec.rb +19 -9
  76. data/spec/functional/associations_spec.rb +3 -3
  77. data/spec/functional/binary_spec.rb +2 -2
  78. data/spec/functional/caching_spec.rb +15 -22
  79. data/spec/functional/callbacks_spec.rb +2 -2
  80. data/spec/functional/counter_cache_spec.rb +10 -10
  81. data/spec/functional/dirty_spec.rb +48 -10
  82. data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
  83. data/spec/functional/document_spec.rb +5 -8
  84. data/spec/functional/dumpable_spec.rb +1 -1
  85. data/spec/functional/embedded_document_spec.rb +5 -5
  86. data/spec/functional/identity_map_spec.rb +8 -8
  87. data/spec/functional/indexes_spec.rb +19 -18
  88. data/spec/functional/keys_spec.rb +64 -33
  89. data/spec/functional/logger_spec.rb +2 -2
  90. data/spec/functional/modifiers_spec.rb +81 -19
  91. data/spec/functional/partial_updates_spec.rb +8 -8
  92. data/spec/functional/protected_spec.rb +1 -1
  93. data/spec/functional/querying_spec.rb +70 -22
  94. data/spec/functional/safe_spec.rb +23 -27
  95. data/spec/functional/sci_spec.rb +7 -7
  96. data/spec/functional/scopes_spec.rb +89 -1
  97. data/spec/functional/static_keys_spec.rb +2 -2
  98. data/spec/functional/stats_spec.rb +28 -12
  99. data/spec/functional/strong_parameters_spec.rb +49 -0
  100. data/spec/functional/validations_spec.rb +8 -16
  101. data/spec/quality_spec.rb +1 -1
  102. data/spec/spec_helper.rb +39 -8
  103. data/spec/support/matchers.rb +1 -1
  104. data/spec/unit/associations/proxy_spec.rb +18 -10
  105. data/spec/unit/clone_spec.rb +1 -1
  106. data/spec/unit/document_spec.rb +3 -3
  107. data/spec/unit/embedded_document_spec.rb +4 -5
  108. data/spec/unit/extensions_spec.rb +12 -7
  109. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  110. data/spec/unit/inspect_spec.rb +1 -1
  111. data/spec/unit/key_spec.rb +23 -18
  112. data/spec/unit/keys_spec.rb +17 -8
  113. data/spec/unit/mongo_mapper_spec.rb +41 -88
  114. data/spec/unit/rails_spec.rb +2 -2
  115. data/spec/unit/validations_spec.rb +18 -18
  116. metadata +70 -38
  117. data/README.rdoc +0 -56
  118. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
  119. data/lib/mongo_mapper/plugins/associations/collection.rb +0 -29
  120. data/lib/mongo_mapper/plugins/associations/proxy.rb +0 -141
@@ -91,6 +91,12 @@ describe "Accessible" do
91
91
  @doc.admin.should be_falsey
92
92
  end
93
93
 
94
+ it "should ignore inaccessible attribute on #assign_attributes" do
95
+ @doc.assign_attributes({:name => 'Ren Hoek', :admin => true})
96
+ @doc.name.should == 'Ren Hoek'
97
+ @doc.admin.should be_falsey
98
+ end
99
+
94
100
  it "should be indifferent to whether the accessible keys are strings or symbols" do
95
101
  @doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
96
102
  @doc.name.should == 'Stimpson J. Cat'
@@ -119,7 +125,7 @@ describe "Accessible" do
119
125
  key :name, String
120
126
  key :site_id, ObjectId
121
127
  end
122
- GrandParent.collection.remove
128
+ GrandParent.collection.drop
123
129
 
124
130
  class ::Child < ::GrandParent
125
131
  attr_accessible :position
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
 
4
4
  describe "BelongsToPolymorphicProxy" do
5
5
  before do
6
- Status.collection.remove
7
- Project.collection.remove
6
+ Status.collection.drop
7
+ Project.collection.drop
8
8
  end
9
9
 
10
10
  it "should default to nil" do
@@ -51,7 +51,7 @@ describe "BelongsToProxy" do
51
51
  it "should not reload the association when replacing" do
52
52
  post = @post_class.new(:name => 'mongomapper')
53
53
  comment = @comment_class.new(:name => 'Foo!', :post => post)
54
- comment.post.proxy_target.object_id.should == post.object_id
54
+ comment.post.object_id.should == post.object_id
55
55
  end
56
56
 
57
57
  it "should properly assign the associated object when assigning the association with create" do
@@ -121,13 +121,13 @@ describe "BelongsToProxy" do
121
121
  class ::Property
122
122
  include MongoMapper::Document
123
123
  end
124
- Property.collection.remove
124
+ Property.collection.drop
125
125
 
126
126
  class ::Thing
127
127
  include MongoMapper::Document
128
128
  key :name, String
129
129
  end
130
- Thing.collection.remove
130
+ Thing.collection.drop
131
131
  end
132
132
 
133
133
  after do
@@ -211,7 +211,7 @@ describe "BelongsToProxy" do
211
211
  end
212
212
 
213
213
  it "should raise exception if invalid" do
214
- expect { comment.create_post! }.to raise_error(MongoMapper::DocumentNotValid)
214
+ lambda { comment.create_post! }.should raise_error(MongoMapper::DocumentNotValid)
215
215
  end
216
216
 
217
217
  it "should work if valid" do
@@ -252,4 +252,54 @@ describe "BelongsToProxy" do
252
252
  post.reload.title.should == 'Hello, world!'
253
253
  end
254
254
  end
255
- end
255
+
256
+ context "regression with reassignment" do
257
+ it "should not infinite regress (shouldn't raise SystemStackError) when assigned to twice (when the proxy isn't around)" do
258
+ post = @post_class.create!
259
+ comment = @comment_class.create!(post: post)
260
+
261
+ comment = @comment_class.find(comment.id)
262
+
263
+ post = comment.post
264
+
265
+ comment.post = post
266
+
267
+ lambda do
268
+ comment.post = post
269
+ end.should_not raise_error
270
+ end
271
+ end
272
+
273
+ context "foreign_key=" do
274
+ it "should reset parent when foreign key is changed" do
275
+ post = @post_class.create!
276
+ comment = @comment_class.create!(post: post)
277
+ another_post = @post_class.create!
278
+
279
+ comment.post.should == post
280
+
281
+ comment.post_id = another_post.id
282
+
283
+ comment.post.should == another_post
284
+
285
+ comment.post_id = nil
286
+
287
+ comment.post.should == nil
288
+ end
289
+
290
+ it "should reset parent when foreign key is changed from nil" do
291
+ post = @post_class.create!
292
+ comment = @comment_class.create!(post: nil)
293
+
294
+ comment.post.should == nil
295
+
296
+ comment.post_id = post.id
297
+
298
+ comment.post.should == post
299
+
300
+ comment.post_id = nil
301
+
302
+ comment.post.should == nil
303
+ end
304
+ end
305
+ end
@@ -14,8 +14,8 @@ describe "InArrayProxy" do
14
14
  key :list_ids, Array
15
15
  many :lists, :in => :list_ids
16
16
  end
17
- User.collection.remove
18
- List.collection.remove
17
+ User.collection.drop
18
+ List.collection.drop
19
19
  end
20
20
 
21
21
  after do
@@ -112,9 +112,9 @@ describe "InArrayProxy" do
112
112
  end
113
113
 
114
114
  it "should raise exception if invalid" do
115
- expect {
115
+ lambda {
116
116
  @user.lists.create!
117
- }.to raise_error(MongoMapper::DocumentNotValid)
117
+ }.should raise_error(MongoMapper::DocumentNotValid)
118
118
  end
119
119
 
120
120
  it "should reset cache" do
@@ -144,7 +144,7 @@ describe "InArrayProxy" do
144
144
 
145
145
  it "should not hit the database if ids key is empty" do
146
146
  @user.list_ids = []
147
- expect(@user.lists).to receive(:query).never
147
+ @user.lists.should_receive(:query).never
148
148
  @user.lists.all.should == []
149
149
  end
150
150
  end
@@ -160,7 +160,7 @@ describe "InArrayProxy" do
160
160
 
161
161
  it "should not hit the database if ids key is empty" do
162
162
  @user.list_ids = []
163
- expect(@user.lists).to receive(:query).never
163
+ @user.lists.should_receive(:query).never
164
164
  @user.lists.first.should be_nil
165
165
  end
166
166
  end
@@ -176,7 +176,7 @@ describe "InArrayProxy" do
176
176
 
177
177
  it "should not hit the database if ids key is empty" do
178
178
  @user.list_ids = []
179
- expect(@user.lists).to receive(:query).never
179
+ @user.lists.should_receive(:query).never
180
180
  @user.lists.last.should be_nil
181
181
  end
182
182
  end
@@ -195,9 +195,9 @@ describe "InArrayProxy" do
195
195
  end
196
196
 
197
197
  it "should raise error when using ! and not found" do
198
- expect {
198
+ lambda {
199
199
  @user.lists.find!(@list3.id)
200
- }.to raise_error(MongoMapper::DocumentNotFound)
200
+ }.should raise_error(MongoMapper::DocumentNotFound)
201
201
  end
202
202
  end
203
203
 
@@ -230,7 +230,7 @@ describe "InArrayProxy" do
230
230
 
231
231
  it "should not hit the database if ids key is empty" do
232
232
  @user.list_ids = []
233
- expect(@user.lists).to receive(:query).never
233
+ @user.lists.should_receive(:query).never
234
234
  @user.lists.paginate(:page => 1).should == []
235
235
  end
236
236
  end
@@ -249,9 +249,9 @@ describe "InArrayProxy" do
249
249
  end
250
250
 
251
251
  it "should raise error when using ! and not found" do
252
- expect {
252
+ lambda {
253
253
  @user.lists.find_by_name!('Foo 3')
254
- }.to raise_error(MongoMapper::DocumentNotFound)
254
+ }.should raise_error(MongoMapper::DocumentNotFound)
255
255
  end
256
256
 
257
257
  context "find_or_create_by" do
@@ -293,7 +293,7 @@ describe "InArrayProxy" do
293
293
 
294
294
  it "should not hit the database if ids key is empty" do
295
295
  @user.list_ids = []
296
- expect(@user.lists).to receive(:query).never
296
+ @user.lists.should_receive(:query).never
297
297
  @user.lists.count(:name => 'Foo 1').should == 0
298
298
  end
299
299
  end
@@ -346,4 +346,139 @@ describe "InArrayProxy" do
346
346
  end
347
347
  end
348
348
  end
349
- end
349
+
350
+ describe "ordering" do
351
+ before do
352
+ @user_class = Doc("User") do
353
+ key :list_ids, Array
354
+ end
355
+
356
+ @list_class = Doc("List") do
357
+ key :name, String, :required => true
358
+ end
359
+ end
360
+
361
+ def create_list_items
362
+ @user = @user_class.create!
363
+ @list1 = @list_class.create!(:name => "one")
364
+ @list2 = @list_class.create!(:name => "two")
365
+ @list3 = @list_class.create!(:name => "three")
366
+
367
+ @user.lists << [@list3, @list2, @list1]
368
+ @user.save!
369
+
370
+ @user.reload
371
+ end
372
+
373
+ shared_examples_for "ordering is on" do
374
+ it "should have the items ordered according to order of the ids" do
375
+ @user.lists.should == [@list3, @list2, @list1]
376
+ end
377
+
378
+ it "should have the right item for #first" do
379
+ @user.lists.first.should == @list3
380
+ end
381
+
382
+ it "should have the right item for #last" do
383
+ @user.lists.last.should == @list1
384
+ end
385
+
386
+ it "does not work for pagination (but probably should)" do
387
+ @user.lists.paginate(:per_page => 100).should == [@list1, @list2, @list3]
388
+ end
389
+
390
+ it "should work with find" do
391
+ @user.lists.find(@list2.id, @list1.id).should == [@list2, @list1]
392
+ @user.lists.find(@list1.id, @list2.id).should == [@list2, @list1]
393
+ @user.lists.find(@list1.id).should == @list1
394
+ end
395
+
396
+ it "should work with find!" do
397
+ @user.lists.find!(@list2.id, @list1.id).should == [@list2, @list1]
398
+ @user.lists.find!(@list1.id, @list2.id).should == [@list2, @list1]
399
+ end
400
+
401
+ it "should only load one object with first (and no params given)" do
402
+ @list_class.should_receive(:allocate).once.and_return @list3
403
+ @user.lists.first
404
+ end
405
+
406
+ it "should only load one object with first (and params given)" do
407
+ @list_class.should_receive(:allocate).once.and_return @list3
408
+ @user.lists.first(:name => /^t/)
409
+ end
410
+
411
+ it "should only load one object with last (and no params given)" do
412
+ @list_class.should_receive(:allocate).once.and_return @list1
413
+ @user.lists.last
414
+ end
415
+
416
+ it "should only load one object with last (and params given)" do
417
+ @list_class.should_receive(:allocate).once.and_return @list3
418
+ @user.lists.last(:name => /^t/)
419
+ end
420
+
421
+ it "should return nil if first with a query matches no objects" do
422
+ @user.lists.first(:name => "non-existent").should be_nil
423
+ end
424
+
425
+ it "should return nil if last with a query matches no objects" do
426
+ @user.lists.last(:name => "non-existent").should be_nil
427
+ end
428
+
429
+ it "should work with extra query params to first and last" do
430
+ @user.lists.first(:name => /^t/).should == @list3
431
+ @user.lists.first(:name => /^o/).should == @list1
432
+
433
+ @user.lists.last(:name => /^t/).should == @list2
434
+ @user.lists.last(:name => /^o/).should == @list1
435
+ end
436
+ end
437
+
438
+ shared_examples_for "ordering is off" do
439
+ it "should include all items" do
440
+ @user.lists.length == 3
441
+ @user.lists.should include(@list1)
442
+ @user.lists.should include(@list2)
443
+ @user.lists.should include(@list3)
444
+ end
445
+
446
+ it "should return the items in the natural order" do
447
+ @user.lists.should == [@list1, @list2, @list3]
448
+ end
449
+
450
+ it "should work with find" do
451
+ @user.lists.find(@list2.id, @list1.id).should == [@list1, @list2]
452
+ @user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
453
+ @user.lists.find(@list1.id).should == @list1
454
+ end
455
+ end
456
+
457
+ describe "without a param" do
458
+ before do
459
+ @user_class.many :lists, :in => :list_ids, :class => @list_class
460
+ create_list_items
461
+ end
462
+
463
+ it_behaves_like "ordering is off"
464
+ end
465
+
466
+ describe "with ordering off" do
467
+ before do
468
+ @user_class.many :lists, :in => :list_ids, :class => @list_class, :ordered => false
469
+ create_list_items
470
+ end
471
+
472
+ it_behaves_like "ordering is off"
473
+ end
474
+
475
+ describe "with ordering on" do
476
+ before do
477
+ @user_class.many :lists, :in => :list_ids, :class => @list_class, :ordered => true
478
+ create_list_items
479
+ end
480
+
481
+ it_behaves_like "ordering is on"
482
+ end
483
+ end
484
+ end
@@ -0,0 +1,321 @@
1
+ require 'spec_helper'
2
+
3
+ describe "InForeignArrayProxyTest" do
4
+ context "description" do
5
+ before do
6
+ class ::List
7
+ include MongoMapper::Document
8
+ key :name, String, :required => true
9
+ key :user_ids, Array
10
+ many :users, :in => :user_ids
11
+ end
12
+
13
+ class ::User
14
+ include MongoMapper::Document
15
+ key :name, String, :required => true
16
+ many :lists, :from => :user_ids, :as => :user
17
+ end
18
+ User.collection.drop
19
+ List.collection.drop
20
+ end
21
+
22
+ after do
23
+ Object.send :remove_const, 'List' if defined?(::List)
24
+ Object.send :remove_const, 'User' if defined?(::User)
25
+ end
26
+
27
+ it "should default reader to empty array" do
28
+ User.new.lists.should == []
29
+ end
30
+
31
+ it "should allow adding to association like it was an array" do
32
+ user = User.new(:name => 'John')
33
+ user.lists << List.new(:name => 'Foo1!')
34
+ user.lists.push List.new(:name => 'Foo2!')
35
+ user.lists.concat List.new(:name => 'Foo3!')
36
+ user.lists.size.should == 3
37
+ end
38
+
39
+ it "should ignore adding duplicate ids" do
40
+ user = User.create(:name => 'John')
41
+ list = List.create(:name => 'Foo')
42
+ user.lists << list
43
+ user.lists << list
44
+ user.lists << list
45
+
46
+ list.reload.user_ids.should == [user.id]
47
+ user.lists.count.should == 1
48
+ end
49
+
50
+ it "should be able to replace the association" do
51
+ user = User.new(:name => 'John')
52
+ list = List.new(:name => 'Foo')
53
+ user.lists = [list]
54
+ user.save.should == true
55
+
56
+ user.reload
57
+ list.reload
58
+ list.user_ids.should == [user.id]
59
+ user.lists.size.should == 1
60
+ user.lists[0].name.should == 'Foo'
61
+ end
62
+
63
+ context "create" do
64
+ before do
65
+ @user = User.create(:name => 'John')
66
+ @list = @user.lists.create(:name => 'Foo!')
67
+ end
68
+
69
+ it "should add id to key" do
70
+ @list.user_ids.should include(@user.id)
71
+ end
72
+
73
+ it "should persist id addition to key in database" do
74
+ @list.reload
75
+ @list.user_ids.should include(@user.id)
76
+ end
77
+
78
+ it "should add doc to association" do
79
+ @user.lists.should include(@list)
80
+ end
81
+
82
+ it "should save doc" do
83
+ @list.should_not be_new
84
+ end
85
+
86
+ it "should reset cache" do
87
+ @user.lists.size.should == 1
88
+ @user.lists.create(:name => 'Moo!')
89
+ @user.lists.size.should == 2
90
+ end
91
+ end
92
+
93
+ context "create!" do
94
+ before do
95
+ @user = User.create(:name => 'John')
96
+ @list = @user.lists.create!(:name => 'Foo!')
97
+ end
98
+
99
+ it "should add id to key" do
100
+ @list.user_ids.should include(@user.id)
101
+ end
102
+
103
+ it "should persist id addition to key in database" do
104
+ @list.reload
105
+ @list.user_ids.should include(@user.id)
106
+ end
107
+
108
+ it "should add doc to association" do
109
+ @user.lists.should include(@list)
110
+ end
111
+
112
+ it "should save doc" do
113
+ @list.should_not be_new
114
+ end
115
+
116
+ it "should raise exception if invalid" do
117
+ lambda do
118
+ @user.lists.create!
119
+ end.should raise_error(MongoMapper::DocumentNotValid)
120
+ end
121
+
122
+ it "should reset cache" do
123
+ @user.lists.size.should == 1
124
+ @user.lists.create!(:name => 'Moo!')
125
+ @user.lists.size.should == 2
126
+ end
127
+ end
128
+
129
+ context "Finding scoped to association" do
130
+ before do
131
+ @user = User.create(:name => 'John')
132
+ @user2 = User.create(:name => 'Brandon')
133
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
134
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
135
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
136
+ end
137
+
138
+ context "all" do
139
+ it "should work" do
140
+ @user.lists.all(:order => :position.asc).should == [@list1, @list2]
141
+ end
142
+
143
+ it "should work with conditions" do
144
+ @user.lists.all(:name => 'Foo 1').should == [@list1]
145
+ end
146
+ end
147
+
148
+ context "first" do
149
+ it "should work" do
150
+ @user.lists.first(:order => 'position').should == @list1
151
+ end
152
+
153
+ it "should work with conditions" do
154
+ @user.lists.first(:position => 2).should == @list2
155
+ end
156
+ end
157
+
158
+ context "last" do
159
+ it "should work" do
160
+ @user.lists.last(:order => 'position').should == @list2
161
+ end
162
+
163
+ it "should work with conditions" do
164
+ @user.lists.last(:position => 2, :order => 'position').should == @list2
165
+ end
166
+ end
167
+
168
+ context "with one id" do
169
+ it "should work for id in association" do
170
+ @user.lists.find(@list1.id).should == @list1
171
+ end
172
+
173
+ it "should work with string ids" do
174
+ @user.lists.find(@list1.id.to_s).should == @list1
175
+ end
176
+
177
+ it "should not work for id not in association" do
178
+ @user.lists.find(@list3.id).should be_nil
179
+ end
180
+
181
+ it "should raise error when using ! and not found" do
182
+ lambda do
183
+ @user.lists.find!(@list3.id)
184
+ end.should raise_error(MongoMapper::DocumentNotFound)
185
+ end
186
+ end
187
+
188
+ context "with multiple ids" do
189
+ it "should work for ids in association" do
190
+ @user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
191
+ end
192
+
193
+ it "should not work for ids not in association" do
194
+ @user.lists.find(@list1.id, @list2.id, @list3.id).should == [@list1, @list2]
195
+ end
196
+ end
197
+
198
+ context "with #paginate" do
199
+ before do
200
+ @lists = @user.lists.paginate(:per_page => 1, :page => 1, :order => 'position')
201
+ end
202
+
203
+ it "should return total pages" do
204
+ @lists.total_pages.should == 2
205
+ end
206
+
207
+ it "should return total entries" do
208
+ @lists.total_entries.should == 2
209
+ end
210
+
211
+ it "should return the subject" do
212
+ @lists.collect(&:name).should == ['Foo 1']
213
+ end
214
+ end
215
+
216
+ context "dynamic finders" do
217
+ it "should work with single key" do
218
+ @user.lists.find_by_name('Foo 1').should == @list1
219
+ @user.lists.find_by_name!('Foo 1').should == @list1
220
+ @user.lists.find_by_name('Foo 3').should be_nil
221
+ end
222
+
223
+ it "should work with multiple keys" do
224
+ @user.lists.find_by_name_and_position('Foo 1', 1).should == @list1
225
+ @user.lists.find_by_name_and_position!('Foo 1', 1).should == @list1
226
+ @user.lists.find_by_name_and_position('Foo 3', 1).should be_nil
227
+ end
228
+
229
+ it "should raise error when using ! and not found" do
230
+ lambda do
231
+ @user.lists.find_by_name!('Foo 3')
232
+ end.should raise_error(MongoMapper::DocumentNotFound)
233
+ end
234
+
235
+ context "find_or_create_by" do
236
+ it "should not create document if found" do
237
+ lambda {
238
+ list = @user.lists.find_or_create_by_name('Foo 1')
239
+ list.should == @list1
240
+ }.should_not change { List.count }
241
+ end
242
+
243
+ it "should create document if not found" do
244
+ lambda {
245
+ list = @user.lists.find_or_create_by_name('Home')
246
+ @user.lists.should include(list)
247
+ }.should change { List.count }
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ context "count" do
254
+ before do
255
+ @user = User.create(:name => 'John')
256
+ @user2 = User.create(:name => 'Brandon')
257
+ @list1 = @user.lists.create!(:name => 'Foo 1')
258
+ @list2 = @user.lists.create!(:name => 'Foo 2')
259
+ @list3 = @user2.lists.create!(:name => 'Foo 3')
260
+ end
261
+
262
+ it "should return number of ids" do
263
+ @user.lists.count.should == 2
264
+ @user2.lists.count.should == 1
265
+ end
266
+
267
+ it "should return correct count when given criteria" do
268
+ @user.lists.count(:name => 'Foo 1').should == 1
269
+ @user2.lists.count(:name => 'Foo 1').should == 0
270
+ end
271
+ end
272
+
273
+ context "Removing documents" do
274
+ before do
275
+ @user = User.create(:name => 'John')
276
+ @user2 = User.create(:name => 'Brandon')
277
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
278
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
279
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
280
+ end
281
+
282
+ context "destroy_all" do
283
+ it "should work" do
284
+ @user.lists.count.should == 2
285
+ @user.lists.destroy_all
286
+ @user.lists.count.should == 0
287
+ end
288
+
289
+ it "should work with conditions" do
290
+ @user.lists.count.should == 2
291
+ @user.lists.destroy_all(:name => 'Foo 1')
292
+ @user.lists.count.should == 1
293
+ end
294
+ end
295
+
296
+ context "delete_all" do
297
+ it "should work" do
298
+ @user.lists.count.should == 2
299
+ @user.lists.delete_all
300
+ @user.lists.count.should == 0
301
+ end
302
+
303
+ it "should work with conditions" do
304
+ @user.lists.count.should == 2
305
+ @user.lists.delete_all(:name => 'Foo 1')
306
+ @user.lists.count.should == 1
307
+ end
308
+ end
309
+
310
+ it "should work with nullify" do
311
+ @user.lists.count.should == 2
312
+
313
+ lambda {
314
+ @user.lists.nullify
315
+ }.should_not change { List.count }
316
+
317
+ @user.lists.count.should == 0
318
+ end
319
+ end
320
+ end
321
+ end