mongodoc 0.2.1 → 0.2.2

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 (44) hide show
  1. data/README.textile +42 -12
  2. data/Rakefile +4 -4
  3. data/TODO +26 -0
  4. data/VERSION +1 -1
  5. data/examples/simple_document.rb +1 -1
  6. data/examples/simple_object.rb +0 -2
  7. data/features/mongodb.yml +6 -5
  8. data/features/removing_documents.feature +68 -0
  9. data/features/step_definitions/collection_steps.rb +3 -3
  10. data/features/step_definitions/document_steps.rb +2 -2
  11. data/features/step_definitions/removing_documents_steps.rb +14 -0
  12. data/features/support/support.rb +2 -2
  13. data/lib/mongodoc.rb +4 -7
  14. data/lib/mongodoc/associations/collection_proxy.rb +103 -0
  15. data/lib/mongodoc/associations/document_proxy.rb +53 -0
  16. data/lib/mongodoc/associations/hash_proxy.rb +96 -0
  17. data/lib/mongodoc/associations/proxy_base.rb +51 -0
  18. data/lib/mongodoc/attributes.rb +49 -17
  19. data/lib/mongodoc/collection.rb +15 -5
  20. data/lib/mongodoc/connection.rb +83 -20
  21. data/lib/mongodoc/criteria.rb +9 -4
  22. data/lib/mongodoc/cursor.rb +9 -3
  23. data/lib/mongodoc/document.rb +37 -24
  24. data/lib/mongodoc/validations/macros.rb +11 -0
  25. data/lib/mongodoc/validations/validates_embedded.rb +13 -0
  26. data/mongodb.example.yml +13 -5
  27. data/mongodoc.gemspec +33 -23
  28. data/spec/associations/collection_proxy_spec.rb +200 -0
  29. data/spec/associations/document_proxy_spec.rb +42 -0
  30. data/spec/associations/hash_proxy_spec.rb +163 -0
  31. data/spec/attributes_spec.rb +113 -47
  32. data/spec/bson_spec.rb +24 -24
  33. data/spec/collection_spec.rb +67 -86
  34. data/spec/connection_spec.rb +98 -150
  35. data/spec/criteria_spec.rb +4 -3
  36. data/spec/cursor_spec.rb +33 -27
  37. data/spec/document_spec.rb +173 -156
  38. data/spec/embedded_save_spec.rb +8 -3
  39. data/spec/new_record_spec.rb +33 -121
  40. metadata +80 -39
  41. data/lib/mongodoc/parent_proxy.rb +0 -44
  42. data/lib/mongodoc/proxy.rb +0 -83
  43. data/spec/parent_proxy_spec.rb +0 -44
  44. data/spec/proxy_spec.rb +0 -80
@@ -121,6 +121,7 @@ describe MongoDoc::Criteria do
121
121
 
122
122
  before do
123
123
  @count = 27
124
+ @collection = mock
124
125
  @cursor = stub('cursor', :count => @count)
125
126
  Person.stub(:collection).and_return(@collection)
126
127
  end
@@ -339,9 +340,9 @@ describe MongoDoc::Criteria do
339
340
  @criteria.selector.should == { :_id => id }
340
341
  end
341
342
 
342
- it "adds the string as the _id query to the selector" do
343
- id = Mongo::ObjectID.new.to_s
344
- @criteria.id(id)
343
+ it "when a string adds ObjectID as the _id query to the selector" do
344
+ id = Mongo::ObjectID.new
345
+ @criteria.id(id.to_s)
345
346
  @criteria.selector.should == { :_id => id }
346
347
  end
347
348
 
@@ -1,85 +1,91 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "MongoDoc::Cursor" do
4
- before do
5
- @mongo_cursor = stub('cursor')
6
- @cursor = MongoDoc::Cursor.new(@mongo_cursor)
7
- end
4
+ let(:mongo_cursor) { stub('cursor') }
5
+
6
+ let(:collection) { stub('collection') }
7
+
8
+ let(:cursor) { MongoDoc::Cursor.new(collection, mongo_cursor) }
8
9
 
9
10
  it "is Enumerable" do
10
- Enumerable.should === @cursor
11
+ Enumerable.should === cursor
11
12
  end
12
13
 
13
14
  it ".new wraps a Mongo::Cursor" do
14
- @cursor._cursor.should == @mongo_cursor
15
+ cursor._cursor.should == mongo_cursor
16
+ end
17
+
18
+ it "#collection returns the MongoDoc::Collection for this cursor" do
19
+ cursor.collection.should == collection
20
+ cursor._collection.should == collection
15
21
  end
16
22
 
17
23
  context "with the underlying cursor" do
18
- %w(close closed? count explain limit query_options_hash query_opts skip sort).each do |delegated_method|
24
+ %w(admin close closed? count explain fields full_collection_name hint limit order query_options_hash query_opts selector skip snapshot sort timeout).each do |delegated_method|
19
25
  it "delegates #{delegated_method} to the Mongo::Cursor" do
20
- @mongo_cursor.should_receive(delegated_method)
21
- @cursor.send(delegated_method)
26
+ mongo_cursor.should_receive(delegated_method)
27
+ cursor.send(delegated_method)
22
28
  end
23
29
  end
24
30
  end
25
31
 
26
32
  context "#each" do
27
33
  it "delegates to the cursor" do
28
- @mongo_cursor.should_receive(:each)
29
- @cursor.each
34
+ mongo_cursor.should_receive(:each)
35
+ cursor.each
30
36
  end
31
37
 
32
38
  it "decodes the return from the delegate" do
33
39
  bson = stub('bson')
34
- @cursor.stub(:_cursor).and_return([bson])
40
+ cursor.stub(:_cursor).and_return([bson])
35
41
  MongoDoc::BSON.should_receive(:decode).with(bson)
36
- @cursor.each {}
42
+ cursor.each {}
37
43
  end
38
44
 
39
45
  it "calls the block with the decoded return" do
40
46
  result = stub('bson')
41
- @cursor.stub(:_cursor).and_return([result])
47
+ cursor.stub(:_cursor).and_return([result])
42
48
  MongoDoc::BSON.stub(:decode).and_return(result)
43
- @cursor.each {|obj| @obj = obj}
49
+ cursor.each {|obj| @obj = obj}
44
50
  @obj.should == result
45
51
  end
46
52
  end
47
53
 
48
54
  context "#next_document" do
49
55
  it "delegates to the cursor" do
50
- @mongo_cursor.should_receive(:next_document)
51
- @cursor.next_document
56
+ mongo_cursor.should_receive(:next_document)
57
+ cursor.next_document
52
58
  end
53
59
 
54
60
  it "decodes the return from the delegate" do
55
61
  bson = stub('bson')
56
- @mongo_cursor.stub(:next_document).and_return(bson)
62
+ mongo_cursor.stub(:next_document).and_return(bson)
57
63
  MongoDoc::BSON.should_receive(:decode).with(bson)
58
- @cursor.next_document
64
+ cursor.next_document
59
65
  end
60
66
 
61
67
  it "returns nil if the delegate returns nil" do
62
- @mongo_cursor.stub(:next_document)
63
- @cursor.next_document.should be_nil
68
+ mongo_cursor.stub(:next_document)
69
+ cursor.next_document.should be_nil
64
70
  end
65
71
  end
66
72
 
67
73
  context "#to_a" do
68
74
  it "delegates to the cursor" do
69
- @mongo_cursor.should_receive(:to_a)
70
- @cursor.to_a
75
+ mongo_cursor.should_receive(:to_a)
76
+ cursor.to_a
71
77
  end
72
78
 
73
79
  it "decodes the return from the delegate" do
74
80
  array = stub('array')
75
- @mongo_cursor.stub(:to_a).and_return(array)
81
+ mongo_cursor.stub(:to_a).and_return(array)
76
82
  MongoDoc::BSON.should_receive(:decode).with(array)
77
- @cursor.to_a
83
+ cursor.to_a
78
84
  end
79
85
 
80
86
  it "returns [] if the delegate returns []" do
81
- @mongo_cursor.stub(:to_a).and_return([])
82
- @cursor.to_a.should == []
87
+ mongo_cursor.stub(:to_a).and_return([])
88
+ cursor.to_a.should == []
83
89
  end
84
90
  end
85
91
  end
@@ -18,8 +18,8 @@ describe "MongoDoc::Document" do
18
18
  @doc.id.should == @doc._id
19
19
  end
20
20
 
21
- it "#to_param returns the _id" do
22
- @doc.to_param.should == @doc._id
21
+ it "#to_param returns the string of the _id" do
22
+ @doc.to_param.should == @doc._id.to_s
23
23
  end
24
24
 
25
25
  context "#new_record?" do
@@ -219,109 +219,64 @@ describe "MongoDoc::Document" do
219
219
  validates_presence_of :data
220
220
  end
221
221
 
222
+ let(:data) { 'data' }
223
+ let(:instance) { CreateTest.new(:data => data) }
224
+
222
225
  before do
223
- @value = 'value'
224
- CreateTest.stub(:_create).and_return(true)
226
+ instance.stub(:save)
227
+ instance.stub(:save!)
225
228
  end
226
229
 
227
230
  context ".create" do
228
- it "creates a new document" do
229
- obj = CreateTest.new
230
- CreateTest.should_receive(:new).and_return(obj)
231
- CreateTest.create
232
- end
233
-
234
- it "delegates to _create with safe => false" do
235
- obj = CreateTest.new(:data => @value)
236
- CreateTest.stub(:new).and_return(obj)
237
- CreateTest.should_receive(:_create).with(obj, false).and_return(true)
238
- CreateTest.create(:data => @value)
239
- end
240
-
241
- it "sets the passed attributes" do
242
- CreateTest.create(:data => @value).data.should == @value
231
+ it "creates a new document with the attributes" do
232
+ CreateTest.should_receive(:new).with(:data => data).and_return(instance)
233
+ CreateTest.create(:data => data)
243
234
  end
244
235
 
245
- it "returns a valid document" do
246
- CreateTest.should === CreateTest.create(:data => @value)
247
- end
236
+ context "with the new document" do
237
+ before do
238
+ CreateTest.stub(:new).and_return(instance)
239
+ end
248
240
 
249
- it "validates" do
250
- CreateTest.create.errors.should_not be_empty
251
- end
241
+ it "calls save on the instance with safe => false" do
242
+ instance.should_receive(:save).with(false)
243
+ CreateTest.create(:data => data)
244
+ end
252
245
 
253
- it "returns an invalid document" do
254
- CreateTest.should === CreateTest.create
246
+ it "returns the new object" do
247
+ CreateTest.create(:data => data).should == instance
248
+ end
255
249
  end
256
250
  end
257
251
 
258
252
  context ".create!" do
259
- it "creates a new document" do
260
- obj = CreateTest.new
261
- CreateTest.should_receive(:new).and_return(obj)
262
- CreateTest.create! rescue nil
253
+ it "creates a new document with the attributes" do
254
+ CreateTest.should_receive(:new).with(:data => data).and_return(instance)
255
+ CreateTest.create!(:data => data)
263
256
  end
264
257
 
265
- it "delegates to _create with safe => true" do
266
- obj = CreateTest.new(:data => @value)
267
- CreateTest.stub(:new).and_return(obj)
268
- CreateTest.should_receive(:_create).with(obj, true).and_return(true)
269
- CreateTest.create!(:data => @value)
270
- end
271
-
272
- it "sets the passed attributes" do
273
- CreateTest.create!(:data => @value).data.should == @value
274
- end
258
+ context "with the new document" do
259
+ before do
260
+ CreateTest.stub(:new).and_return(instance)
261
+ end
275
262
 
276
- it "returns a valid document" do
277
- CreateTest.should === CreateTest.create!(:data => @value)
278
- end
263
+ it "calls save! on the instance" do
264
+ instance.should_receive(:save!)
265
+ CreateTest.create!(:data => data)
266
+ end
279
267
 
280
- it "raises when invalid" do
281
- expect do
282
- CreateTest.create!
283
- end.should raise_error(MongoDoc::DocumentInvalidError)
268
+ it "returns the new object" do
269
+ CreateTest.create!(:data => data).should == instance
270
+ end
284
271
  end
285
272
  end
286
273
  end
287
274
 
288
- context "#_create" do
289
- class CreateTest
290
- include MongoDoc::Document
291
- end
292
-
293
- before do
294
- @collection = stub('collection')
295
- @collection.stub(:insert)
296
- @doc = CreateTest.new
297
- CreateTest.stub(:collection).and_return(@collection)
298
- end
299
-
300
- it "delegates to the collection insert with safe" do
301
- safe = true
302
- @collection.should_receive(:insert).with(@doc, hash_including(:safe => safe))
303
- CreateTest.send(:_create, @doc, safe)
304
- end
305
-
306
- it "sets the _id of the document" do
307
- id = 'id'
308
- @collection.stub(:insert).and_return(id)
309
- CreateTest.send(:_create, @doc, false)
310
- @doc._id.should == id
311
- end
312
-
313
- it "returns the _id" do
314
- id = 'id'
315
- @collection.stub(:insert).and_return(id)
316
- CreateTest.send(:_create, @doc, false).should == id
317
- end
318
- end
319
-
320
275
  context "updating attributes" do
321
276
  class UpdateAttributesRoot
322
277
  include MongoDoc::Document
323
278
 
324
- has_one :update_attribute_child
279
+ has_one :update_attributes_child
325
280
  end
326
281
 
327
282
  class UpdateAttributesChild
@@ -330,104 +285,127 @@ describe "MongoDoc::Document" do
330
285
  key :data
331
286
  end
332
287
 
288
+ let(:data) {'data'}
289
+
290
+ let(:attrs) {{:data => data}}
291
+
292
+ let(:path_attrs) {{'update_attributes_child.data' => data}}
293
+
294
+ let(:doc) do
295
+ doc = UpdateAttributesChild.new
296
+ doc._id = 'id'
297
+ doc.stub(:_naive_update_attributes)
298
+ doc
299
+ end
300
+
333
301
  before do
334
- @data = 'data'
335
- @doc = UpdateAttributesChild.new
336
- UpdateAttributesRoot.new.update_attribute_child = @doc
337
- @attrs = {:data => @data}
338
- @path_attrs = {'update_attribute_child.data' => @data}
339
- @doc.stub(:_naive_update_attributes)
302
+ root = UpdateAttributesRoot.new
303
+ root.update_attributes_child = doc
304
+ root._id = 'id'
340
305
  end
341
306
 
342
307
  context "#update_attributes" do
308
+ it "delegates to save if the object is a new record" do
309
+ check = 'check'
310
+ doc.stub(:new_record?).and_return(true)
311
+ doc.should_receive(:save).and_return(check)
312
+ doc.update_attributes(attrs).should == check
313
+ end
343
314
 
344
315
  it "sets the attributes" do
345
- @doc.update_attributes(@attrs)
346
- @doc.data.should == @data
316
+ doc.update_attributes(attrs)
317
+ doc.data.should == data
347
318
  end
348
319
 
349
320
  it "normalizes the attributes to the parent" do
350
- @doc.should_receive(:_path_to_root)
351
- @doc.update_attributes(@attrs)
321
+ doc.should_receive(:_path_to_root)
322
+ doc.update_attributes(attrs)
352
323
  end
353
324
 
354
325
  it "validates" do
355
- @doc.should_receive(:valid?)
356
- @doc.update_attributes(@attrs)
326
+ doc.should_receive(:valid?)
327
+ doc.update_attributes(attrs)
357
328
  end
358
329
 
359
330
  it "returns false if the object is not valid" do
360
- @doc.stub(:valid?).and_return(false)
361
- @doc.update_attributes(@attrs).should be_false
331
+ doc.stub(:valid?).and_return(false)
332
+ doc.update_attributes(attrs).should be_false
362
333
  end
363
334
 
364
335
  context "if valid" do
365
336
  context "and strict" do
366
337
  it "delegates to _strict_update_attributes" do
367
- strict_attrs = @attrs.merge(:__strict__ => true)
368
- @doc.should_receive(:_strict_update_attributes).with(@path_attrs, false)
369
- @doc.update_attributes(strict_attrs)
338
+ strict_attrs = attrs.merge(:__strict__ => true)
339
+ doc.should_receive(:_strict_update_attributes).with(path_attrs, false)
340
+ doc.update_attributes(strict_attrs)
370
341
  end
371
342
  end
372
343
 
373
344
  context "and naive" do
374
345
  it "delegates to _naive_update_attributes" do
375
- @doc.should_receive(:_naive_update_attributes).with(@path_attrs, false)
376
- @doc.update_attributes(@attrs)
346
+ doc.should_receive(:_naive_update_attributes).with(path_attrs, false)
347
+ doc.update_attributes(attrs)
377
348
  end
378
349
  end
379
350
 
380
351
  it "returns the result of _naive_update_attributes" do
381
352
  result = 'check'
382
- @doc.stub(:_naive_update_attributes).and_return(result)
383
- @doc.update_attributes(@attrs).should == result
353
+ doc.stub(:_naive_update_attributes).and_return(result)
354
+ doc.update_attributes(attrs).should == result
384
355
  end
385
356
  end
386
357
  end
387
358
 
388
359
  context "#update_attributes!" do
360
+ it "delegates to save! if the object is a new record" do
361
+ check = 'check'
362
+ doc.stub(:new_record?).and_return(true)
363
+ doc.should_receive(:save!).and_return(check)
364
+ doc.update_attributes!(attrs).should == check
365
+ end
366
+
389
367
  it "sets the attributes" do
390
- @doc.update_attributes!(@attrs)
391
- @doc.data.should == @data
368
+ doc.update_attributes!(attrs)
369
+ doc.data.should == data
392
370
  end
393
371
 
394
372
  it "normalizes the attributes to the parent" do
395
- @doc.should_receive(:_path_to_root)
396
- @doc.update_attributes!(@attrs)
373
+ doc.should_receive(:_path_to_root)
374
+ doc.update_attributes!(attrs)
397
375
  end
398
376
 
399
377
  it "validates" do
400
- @doc.should_receive(:valid?).and_return(true)
401
- @doc.update_attributes!(@attrs)
378
+ doc.should_receive(:valid?).and_return(true)
379
+ doc.update_attributes!(attrs)
402
380
  end
403
381
 
404
382
  it "raises if not valid" do
405
- @doc.stub(:valid?).and_return(false)
383
+ doc.stub(:valid?).and_return(false)
406
384
  expect do
407
- @doc.update_attributes!(@attrs)
385
+ doc.update_attributes!(attrs)
408
386
  end.should raise_error(MongoDoc::DocumentInvalidError)
409
387
  end
410
388
 
411
389
  context "if valid" do
412
390
  context "and strict" do
413
391
  it "delegates to _strict_update_attributes with safe == true" do
414
- strict_attrs = @attrs.merge(:__strict__ => true)
415
- @doc.should_receive(:_strict_update_attributes).with(@path_attrs, true)
416
- @doc.update_attributes!(strict_attrs)
392
+ strict_attrs = attrs.merge(:__strict__ => true)
393
+ doc.should_receive(:_strict_update_attributes).with(path_attrs, true)
394
+ doc.update_attributes!(strict_attrs)
417
395
  end
418
396
  end
419
397
 
420
398
  context "and naive" do
421
399
  it "delegates to _naive_update_attributes with safe == true" do
422
- @doc.should_receive(:_naive_update_attributes).with(@path_attrs, true)
423
- @doc.update_attributes!(@attrs)
400
+ doc.should_receive(:_naive_update_attributes).with(path_attrs, true)
401
+ doc.update_attributes!(attrs)
424
402
  end
425
403
  end
426
404
 
427
405
  it "returns the result of _naive_update_attributes" do
428
406
  result = 'check'
429
- @doc.stub(:_naive_update_attributes).and_return(result)
430
- @doc.update_attributes!(@attrs).should == result
407
+ doc.stub(:_naive_update_attributes).and_return(result)
408
+ doc.update_attributes!(attrs).should == result
431
409
  end
432
410
  end
433
411
  end
@@ -438,27 +416,29 @@ describe "MongoDoc::Document" do
438
416
  include MongoDoc::Document
439
417
  end
440
418
 
441
- before do
442
- @id = 'id'
443
- @attrs = {:data => 'data'}
444
- @safe = false
445
- @doc = NaiveUpdateAttributes.new
446
- @doc.stub(:_id).and_return(@id)
447
- @collection = stub('collection')
448
- @collection.stub(:update)
449
- @doc.stub(:_collection).and_return(@collection)
419
+
420
+ let(:id) { 'id' }
421
+
422
+ let(:attrs) { {:data => 'data'} }
423
+
424
+ let(:safe) { false }
425
+
426
+ let(:doc) do
427
+ doc = NaiveUpdateAttributes.new
428
+ doc.stub(:_id).and_return(id)
429
+ doc
450
430
  end
451
431
 
452
- it "calls update on the collection without a root" do
453
- @collection.should_receive(:update).with({'_id' => @id}, MongoDoc::Query.set_modifier(@attrs), {:safe => @safe})
454
- @doc.send(:_naive_update_attributes, @attrs, @safe)
432
+ it "without a root delegates to _update" do
433
+ doc.should_receive(:_update).with({}, attrs, safe)
434
+ doc.send(:_naive_update_attributes, attrs, safe)
455
435
  end
456
436
 
457
437
  it "with a root, calls _naive_update_attributes on the root" do
458
438
  root = NaiveUpdateAttributes.new
459
- @doc.stub(:_root).and_return(root)
460
- root.should_receive(:_naive_update_attributes).with(@attrs, @safe)
461
- @doc.send(:_naive_update_attributes, @attrs, @safe)
439
+ doc.stub(:_root).and_return(root)
440
+ root.should_receive(:_naive_update_attributes).with(attrs, safe)
441
+ doc.send(:_naive_update_attributes, attrs, safe)
462
442
  end
463
443
  end
464
444
 
@@ -467,41 +447,45 @@ describe "MongoDoc::Document" do
467
447
  include MongoDoc::Document
468
448
  end
469
449
 
470
- before do
471
- @id = 'id'
472
- @attrs = {:data => 'data'}
473
- @selector = {'selector' => 'selector'}
474
- @safe = false
475
- @doc = StrictUpdateAttributes.new
476
- @doc.stub(:_id).and_return(@id)
477
- @collection = stub('collection')
478
- @collection.stub(:update)
479
- @doc.stub(:_collection).and_return(@collection)
450
+ let(:id) { 'id' }
451
+
452
+ let(:attrs) { {:data => 'data'} }
453
+
454
+ let(:selector) { {:selector => 'selector'} }
455
+
456
+ let(:safe) { false }
457
+
458
+ let(:doc) do
459
+ doc = StrictUpdateAttributes.new
460
+ doc.stub(:_id).and_return(id)
461
+ doc
480
462
  end
481
463
 
482
464
  context "without a root" do
483
- it "calls update on the collection" do
484
- @collection.should_receive(:update).with({'_id' => @id}.merge(@selector), MongoDoc::Query.set_modifier(@attrs), :safe => @safe)
485
- @doc.send(:_strict_update_attributes, @attrs, @safe, @selector)
465
+ it "without a root delegates to _update" do
466
+ doc.should_receive(:_update).with(selector, attrs, safe)
467
+ doc.send(:_strict_update_attributes, attrs, safe, selector)
486
468
  end
487
469
  end
488
470
 
489
471
  context "with a root" do
472
+ let(:root) { StrictUpdateAttributes.new }
473
+
490
474
  before do
491
- @root = StrictUpdateAttributes.new
492
- @root.stub(:_collection).and_return(@collection)
493
- @doc.stub(:_root).and_return(@root)
494
- @doc.stub(:_selector_path_to_root).and_return({'path._id' => @id})
475
+ doc.stub(:_root).and_return(root)
495
476
  end
496
477
 
497
- it "calls _selector_path_to_root on our id" do
498
- @doc.should_receive(:_selector_path_to_root).with('_id' => @id).and_return({'path._id' => @id})
499
- @doc.send(:_strict_update_attributes, @attrs, @safe)
478
+ it "calls _path_to_root on our id" do
479
+ root.stub(:_strict_update_attributes)
480
+ doc.should_receive(:_path_to_root).with(doc, '_id' => id)
481
+ doc.send(:_strict_update_attributes, attrs, safe)
500
482
  end
501
483
 
502
484
  it "calls _strict_update_attributes on the root with our selector" do
503
- @root.should_receive(:_strict_update_attributes).with(@attrs, @safe, 'path._id' => @id)
504
- @doc.send(:_strict_update_attributes, @attrs, @safe)
485
+ selector = {'path._id' => id}
486
+ doc.stub(:_path_to_root).with(doc, '_id' => id).and_return(selector)
487
+ root.should_receive(:_strict_update_attributes).with(attrs, safe, selector)
488
+ doc.send(:_strict_update_attributes, attrs, safe)
505
489
  end
506
490
  end
507
491
  end
@@ -622,12 +606,45 @@ describe "MongoDoc::Document" do
622
606
 
623
607
  it "roundtrips the proxy" do
624
608
  doc = TestHasManyBsonDoc.new(:subdoc => SubHasManyBsonDoc.new(:attr => "value"))
625
- MongoDoc::Proxy.should === MongoDoc::BSON.decode(doc.to_bson).subdoc
609
+ MongoDoc::Associations::CollectionProxy.should === MongoDoc::BSON.decode(doc.to_bson).subdoc
626
610
  end
627
611
  end
628
612
  end
629
613
  end
630
614
 
615
+ context "removing documents" do
616
+ class RemoveDocument
617
+ include MongoDoc::Document
618
+ end
619
+
620
+ let(:doc) { RemoveDocument.new }
621
+
622
+ context "#remove" do
623
+ it "when called on a embedded document with a _root raises UnsupportedOperation" do
624
+ doc._root = RemoveDocument.new
625
+ expect { doc.remove }.to raise_error(MongoDoc::UnsupportedOperation)
626
+ end
627
+
628
+ it "delegates to remove document" do
629
+ doc.should_receive(:remove_document)
630
+ doc.remove
631
+ end
632
+ end
633
+
634
+ context "#remove_document" do
635
+ it "when the document is the root, removes the document" do
636
+ doc.should_receive(:_remove)
637
+ doc.remove_document
638
+ end
639
+
640
+ it "when the document is not the root, calls remove_document on the root" do
641
+ doc._root = root = RemoveDocument.new
642
+ root.should_receive(:remove_document)
643
+ doc.remove_document
644
+ end
645
+ end
646
+ end
647
+
631
648
  context "misc class methods" do
632
649
  class ClassMethods
633
650
  include MongoDoc::Document
@@ -640,7 +657,7 @@ describe "MongoDoc::Document" do
640
657
  it ".collection returns a wrapped MongoDoc::Collection" do
641
658
  db = stub('db')
642
659
  db.should_receive(:collection).with(ClassMethods.to_s.tableize.gsub('/', '.'))
643
- MongoDoc.should_receive(:database).and_return(db)
660
+ MongoDoc::Connection.should_receive(:database).and_return(db)
644
661
  MongoDoc::Collection.should === ClassMethods.collection
645
662
  end
646
663
  end