mongoid_monkey 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1213 @@
1
+ require "spec_helper"
2
+
3
+ if Mongoid::VERSION =~ /\A3\./
4
+
5
+ describe Mongoid::Relations::Embedded::Many do
6
+
7
+ [ :<<, :push ].each do |method|
8
+
9
+ describe "##{method}" do
10
+
11
+ context "when the parent is a new record" do
12
+
13
+ let(:person) do
14
+ Person.new
15
+ end
16
+
17
+ let(:address) do
18
+ Address.new
19
+ end
20
+
21
+ let!(:added) do
22
+ person.addresses.send(method, address)
23
+ end
24
+
25
+ it "appends to the target" do
26
+ person.addresses.should eq([ address ])
27
+ end
28
+
29
+ it "sets the base on the inverse relation" do
30
+ address.addressable.should eq(person)
31
+ end
32
+
33
+ it "sets the same instance on the inverse relation" do
34
+ address.addressable.should eql(person)
35
+ end
36
+
37
+ it "does not save the new document" do
38
+ address.should_not be_persisted
39
+ end
40
+
41
+ it "sets the parent on the child" do
42
+ address._parent.should eq(person)
43
+ end
44
+
45
+ it "sets the metadata on the child" do
46
+ address.metadata.should_not be_nil
47
+ end
48
+
49
+ it "sets the index on the child" do
50
+ address._index.should eq(0)
51
+ end
52
+
53
+ it "returns the relation" do
54
+ added.should eq(person.addresses)
55
+ end
56
+
57
+ context "with a limiting default scope" do
58
+
59
+ context "when the document matches the scope" do
60
+
61
+ let(:active) do
62
+ Appointment.new
63
+ end
64
+
65
+ before do
66
+ person.appointments.send(method, active)
67
+ end
68
+
69
+ it "appends to the target" do
70
+ person.appointments.target.should eq([ active ])
71
+ end
72
+
73
+ it "appends to the _unscoped" do
74
+ person.appointments.send(:_unscoped).should eq([ active ])
75
+ end
76
+ end
77
+
78
+ context "when the document does not match the scope" do
79
+
80
+ let(:inactive) do
81
+ Appointment.new(active: false)
82
+ end
83
+
84
+ before do
85
+ person.appointments.send(method, inactive)
86
+ end
87
+
88
+ it "doesn't append to the target" do
89
+ person.appointments.target.should_not eq([ inactive ])
90
+ end
91
+
92
+ it "appends to the _unscoped" do
93
+ person.appointments.send(:_unscoped).should eq([ inactive ])
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ context "when the parent is not a new record" do
100
+
101
+ let(:person) do
102
+ Person.create
103
+ end
104
+
105
+ let(:address) do
106
+ Address.new
107
+ end
108
+
109
+ before do
110
+ person.addresses.send(method, address)
111
+ end
112
+
113
+ it "saves the new document" do
114
+ address.should be_persisted
115
+ end
116
+ end
117
+
118
+ context "when appending more than one document at once" do
119
+
120
+ let(:person) do
121
+ Person.create
122
+ end
123
+
124
+ let(:address_one) do
125
+ Address.new
126
+ end
127
+
128
+ let(:address_two) do
129
+ Address.new
130
+ end
131
+
132
+ let!(:added) do
133
+ person.addresses.send(method, [ address_one, address_two ])
134
+ end
135
+
136
+ it "saves the first document" do
137
+ address_one.should be_persisted
138
+ end
139
+
140
+ it "saves the second document" do
141
+ address_two.should be_persisted
142
+ end
143
+
144
+ it "returns the relation" do
145
+ added.should eq(person.addresses)
146
+ end
147
+ end
148
+
149
+ context "when the parent and child have a cyclic relation" do
150
+
151
+ context "when the parent is a new record" do
152
+
153
+ let(:parent_role) do
154
+ Role.new
155
+ end
156
+
157
+ let(:child_role) do
158
+ Role.new
159
+ end
160
+
161
+ before do
162
+ parent_role.child_roles.send(method, child_role)
163
+ end
164
+
165
+ it "appends to the target" do
166
+ parent_role.child_roles.should eq([ child_role ])
167
+ end
168
+
169
+ it "sets the base on the inverse relation" do
170
+ child_role.parent_role.should eq(parent_role)
171
+ end
172
+
173
+ it "sets the same instance on the inverse relation" do
174
+ child_role.parent_role.should eql(parent_role)
175
+ end
176
+
177
+ it "does not save the new document" do
178
+ child_role.should_not be_persisted
179
+ end
180
+
181
+ it "sets the parent on the child" do
182
+ child_role._parent.should eq(parent_role)
183
+ end
184
+
185
+ it "sets the metadata on the child" do
186
+ child_role.metadata.should_not be_nil
187
+ end
188
+
189
+ it "sets the index on the child" do
190
+ child_role._index.should eq(0)
191
+ end
192
+ end
193
+
194
+ context "when the parent is not a new record" do
195
+
196
+ let(:parent_role) do
197
+ Role.create(name: "CEO")
198
+ end
199
+
200
+ let(:child_role) do
201
+ Role.new(name: "COO")
202
+ end
203
+
204
+ before do
205
+ parent_role.child_roles.send(method, child_role)
206
+ end
207
+
208
+ it "saves the new document" do
209
+ child_role.should be_persisted
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ describe "#concat" do
217
+
218
+ context "when the parent is a new record" do
219
+
220
+ let(:person) do
221
+ Person.new
222
+ end
223
+
224
+ let(:address) do
225
+ Address.new
226
+ end
227
+
228
+ before do
229
+ person.addresses.concat([ address ])
230
+ end
231
+
232
+ it "appends to the target" do
233
+ person.addresses.should eq([ address ])
234
+ end
235
+
236
+ it "appends to the unscoped" do
237
+ person.addresses.send(:_unscoped).should eq([ address ])
238
+ end
239
+
240
+ it "sets the base on the inverse relation" do
241
+ address.addressable.should eq(person)
242
+ end
243
+
244
+ it "sets the same instance on the inverse relation" do
245
+ address.addressable.should eql(person)
246
+ end
247
+
248
+ it "does not save the new document" do
249
+ address.should_not be_persisted
250
+ end
251
+
252
+ it "sets the parent on the child" do
253
+ address._parent.should eq(person)
254
+ end
255
+
256
+ it "sets the metadata on the child" do
257
+ address.metadata.should_not be_nil
258
+ end
259
+
260
+ it "sets the index on the child" do
261
+ address._index.should eq(0)
262
+ end
263
+ end
264
+
265
+ context "when the parent is not a new record" do
266
+
267
+ let(:person) do
268
+ Person.create
269
+ end
270
+
271
+ let(:address) do
272
+ Address.new
273
+ end
274
+
275
+ before do
276
+ person.addresses.concat([ address ])
277
+ end
278
+
279
+ it "saves the new document" do
280
+ address.should be_persisted
281
+ end
282
+ end
283
+
284
+ context "when concatenating an empty array" do
285
+
286
+ let(:person) do
287
+ Person.create
288
+ end
289
+
290
+ before do
291
+ person.addresses.should_not_receive(:batch_insert)
292
+ person.addresses.concat([])
293
+ end
294
+
295
+ it "doesn't update the target" do
296
+ person.addresses.should be_empty
297
+ end
298
+ end
299
+
300
+ context "when appending more than one document at once" do
301
+
302
+ let(:person) do
303
+ Person.create
304
+ end
305
+
306
+ let(:address_one) do
307
+ Address.new
308
+ end
309
+
310
+ let(:address_two) do
311
+ Address.new
312
+ end
313
+
314
+ before do
315
+ person.addresses.concat([ address_one, address_two ])
316
+ end
317
+
318
+ it "saves the first document" do
319
+ address_one.should be_persisted
320
+ end
321
+
322
+ it "saves the second document" do
323
+ address_two.should be_persisted
324
+ end
325
+ end
326
+
327
+ context "when the parent and child have a cyclic relation" do
328
+
329
+ context "when the parent is a new record" do
330
+
331
+ let(:parent_role) do
332
+ Role.new
333
+ end
334
+
335
+ let(:child_role) do
336
+ Role.new
337
+ end
338
+
339
+ before do
340
+ parent_role.child_roles.concat([ child_role ])
341
+ end
342
+
343
+ it "appends to the target" do
344
+ parent_role.child_roles.should eq([ child_role ])
345
+ end
346
+
347
+ it "sets the base on the inverse relation" do
348
+ child_role.parent_role.should eq(parent_role)
349
+ end
350
+
351
+ it "sets the same instance on the inverse relation" do
352
+ child_role.parent_role.should eql(parent_role)
353
+ end
354
+
355
+ it "does not save the new document" do
356
+ child_role.should_not be_persisted
357
+ end
358
+
359
+ it "sets the parent on the child" do
360
+ child_role._parent.should eq(parent_role)
361
+ end
362
+
363
+ it "sets the metadata on the child" do
364
+ child_role.metadata.should_not be_nil
365
+ end
366
+
367
+ it "sets the index on the child" do
368
+ child_role._index.should eq(0)
369
+ end
370
+ end
371
+
372
+ context "when the parent is not a new record" do
373
+
374
+ let(:parent_role) do
375
+ Role.create(name: "CEO")
376
+ end
377
+
378
+ let(:child_role) do
379
+ Role.new(name: "COO")
380
+ end
381
+
382
+ before do
383
+ parent_role.child_roles.concat([ child_role ])
384
+ end
385
+
386
+ it "saves the new document" do
387
+ child_role.should be_persisted
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ describe "#count" do
394
+
395
+ let(:person) do
396
+ Person.create
397
+ end
398
+
399
+ before do
400
+ person.addresses.create(street: "Upper")
401
+ person.addresses.build(street: "Bond")
402
+ end
403
+
404
+ it "returns the number of persisted documents" do
405
+ person.addresses.count.should eq(1)
406
+ end
407
+ end
408
+
409
+ describe "#max" do
410
+
411
+ let(:person) do
412
+ Person.new
413
+ end
414
+
415
+ let(:address_one) do
416
+ Address.new(number: 5)
417
+ end
418
+
419
+ let(:address_two) do
420
+ Address.new(number: 10)
421
+ end
422
+
423
+ before do
424
+ person.addresses.push(address_one, address_two)
425
+ end
426
+
427
+ let(:max) do
428
+ person.addresses.max do |a,b|
429
+ a.number <=> b.number
430
+ end
431
+ end
432
+
433
+ it "returns the document with the max value of the supplied field" do
434
+ max.should eq(address_two)
435
+ end
436
+ end
437
+
438
+ describe "#max_by" do
439
+
440
+ let(:person) do
441
+ Person.new
442
+ end
443
+
444
+ let(:address_one) do
445
+ Address.new(number: 5)
446
+ end
447
+
448
+ let(:address_two) do
449
+ Address.new(number: 10)
450
+ end
451
+
452
+ before do
453
+ person.addresses.push(address_one, address_two)
454
+ end
455
+
456
+ let(:max) do
457
+ person.addresses.max_by(&:number)
458
+ end
459
+
460
+ it "returns the document with the max value of the supplied field" do
461
+ max.should eq(address_two)
462
+ end
463
+ end
464
+
465
+ describe "#min" do
466
+
467
+ let(:person) do
468
+ Person.new
469
+ end
470
+
471
+ let(:address_one) do
472
+ Address.new(number: 5)
473
+ end
474
+
475
+ let(:address_two) do
476
+ Address.new(number: 10)
477
+ end
478
+
479
+ before do
480
+ person.addresses.push(address_one, address_two)
481
+ end
482
+
483
+ let(:min) do
484
+ person.addresses.min do |a,b|
485
+ a.number <=> b.number
486
+ end
487
+ end
488
+
489
+ it "returns the min value of the supplied field" do
490
+ min.should eq(address_one)
491
+ end
492
+ end
493
+
494
+ describe "#min_by" do
495
+
496
+ let(:person) do
497
+ Person.new
498
+ end
499
+
500
+ let(:address_one) do
501
+ Address.new(number: 5)
502
+ end
503
+
504
+ let(:address_two) do
505
+ Address.new(number: 10)
506
+ end
507
+
508
+ before do
509
+ person.addresses.push(address_one, address_two)
510
+ end
511
+
512
+ let(:min) do
513
+ person.addresses.min_by(&:number)
514
+ end
515
+
516
+ it "returns the min value of the supplied field" do
517
+ min.should eq(address_one)
518
+ end
519
+ end
520
+
521
+ context "when deeply embedding documents" do
522
+
523
+ context "when updating the bottom level" do
524
+
525
+ let!(:person) do
526
+ Person.create
527
+ end
528
+
529
+ let!(:address) do
530
+ person.addresses.create(street: "Joachimstr")
531
+ end
532
+
533
+ let!(:location) do
534
+ address.locations.create(name: "work")
535
+ end
536
+
537
+ context "when updating with a hash" do
538
+
539
+ before do
540
+ address.update_attributes(locations: [{ name: "home" }])
541
+ end
542
+
543
+ it "updates the attributes" do
544
+ address.locations.first.name.should eq("home")
545
+ end
546
+
547
+ it "overwrites the existing documents" do
548
+ address.locations.count.should eq(1)
549
+ end
550
+
551
+ it "persists the changes" do
552
+ address.reload.locations.count.should eq(1)
553
+ end
554
+ end
555
+ end
556
+
557
+ context "when building the tree through hashes" do
558
+
559
+ let(:circus) do
560
+ Circus.new(hash)
561
+ end
562
+
563
+ let(:animal) do
564
+ circus.animals.first
565
+ end
566
+
567
+ let(:animal_name) do
568
+ "Lion"
569
+ end
570
+
571
+ let(:tag_list) do
572
+ "tigers, bears, oh my"
573
+ end
574
+
575
+ context "when the hash uses stringified keys" do
576
+
577
+ let(:hash) do
578
+ { 'animals' => [{ 'name' => animal_name, 'tag_list' => tag_list }] }
579
+ end
580
+
581
+ it "sets up the hierarchy" do
582
+ animal.circus.should eq(circus)
583
+ end
584
+
585
+ it "assigns the attributes" do
586
+ animal.name.should eq(animal_name)
587
+ end
588
+
589
+ it "uses custom writer methods" do
590
+ animal.tag_list.should eq(tag_list)
591
+ end
592
+ end
593
+
594
+ context "when the hash uses symbolized keys" do
595
+
596
+ let(:hash) do
597
+ { animals: [{ name: animal_name, tag_list: tag_list }] }
598
+ end
599
+
600
+ it "sets up the hierarchy" do
601
+ animal.circus.should eq(circus)
602
+ end
603
+
604
+ it "assigns the attributes" do
605
+ animal.name.should eq(animal_name)
606
+ end
607
+
608
+ it "uses custom writer methods" do
609
+ animal.tag_list.should eq(tag_list)
610
+ end
611
+ end
612
+ end
613
+
614
+ context "when building the tree through pushes" do
615
+
616
+ let(:quiz) do
617
+ Quiz.new
618
+ end
619
+
620
+ let(:page) do
621
+ Page.new
622
+ end
623
+
624
+ let(:page_question) do
625
+ PageQuestion.new
626
+ end
627
+
628
+ before do
629
+ quiz.pages << page
630
+ page.page_questions << page_question
631
+ end
632
+
633
+ let(:question) do
634
+ quiz.pages.first.page_questions.first
635
+ end
636
+
637
+ it "sets up the hierarchy" do
638
+ question.should eq(page_question)
639
+ end
640
+ end
641
+
642
+ context "when building the tree through builds" do
643
+
644
+ let!(:quiz) do
645
+ Quiz.new
646
+ end
647
+
648
+ let!(:page) do
649
+ quiz.pages.build
650
+ end
651
+
652
+ let!(:page_question) do
653
+ page.page_questions.build
654
+ end
655
+
656
+ let(:question) do
657
+ quiz.pages.first.page_questions.first
658
+ end
659
+
660
+ it "sets up the hierarchy" do
661
+ question.should eq(page_question)
662
+ end
663
+ end
664
+
665
+ context "when creating a persisted tree" do
666
+
667
+ let(:quiz) do
668
+ Quiz.create
669
+ end
670
+
671
+ let(:page) do
672
+ Page.new
673
+ end
674
+
675
+ let(:page_question) do
676
+ PageQuestion.new
677
+ end
678
+
679
+ let(:question) do
680
+ quiz.pages.first.page_questions.first
681
+ end
682
+
683
+ before do
684
+ quiz.pages << page
685
+ page.page_questions << page_question
686
+ end
687
+
688
+ it "sets up the hierarchy" do
689
+ question.should eq(page_question)
690
+ end
691
+
692
+ context "when reloading" do
693
+
694
+ let(:from_db) do
695
+ quiz.reload
696
+ end
697
+
698
+ let(:reloaded_question) do
699
+ from_db.pages.first.page_questions.first
700
+ end
701
+
702
+ it "reloads the entire tree" do
703
+ reloaded_question.should eq(question)
704
+ end
705
+ end
706
+ end
707
+ end
708
+
709
+ context "when deeply nesting documents" do
710
+
711
+ context "when all documents are new" do
712
+
713
+ let(:person) do
714
+ Person.new
715
+ end
716
+
717
+ let(:address) do
718
+ Address.new
719
+ end
720
+
721
+ let(:location) do
722
+ Location.new
723
+ end
724
+
725
+ before do
726
+ address.locations << location
727
+ person.addresses << address
728
+ end
729
+
730
+ context "when saving the root" do
731
+
732
+ before do
733
+ person.save
734
+ end
735
+
736
+ it "persists the first level document" do
737
+ person.reload.addresses.first.should eq(address)
738
+ end
739
+
740
+ it "persists the second level document" do
741
+ person.reload.addresses[0].locations.should eq([ location ])
742
+ end
743
+ end
744
+ end
745
+ end
746
+
747
+ context "when attempting nil pushes and substitutes" do
748
+
749
+ let(:home_phone) do
750
+ Phone.new(number: "555-555-5555")
751
+ end
752
+
753
+ let(:office_phone) do
754
+ Phone.new(number: "666-666-6666")
755
+ end
756
+
757
+ describe "replacing the entire embedded list" do
758
+
759
+ context "when an embeds many relationship contains a nil as the first item" do
760
+
761
+ let(:person) do
762
+ Person.create!
763
+ end
764
+
765
+ let(:phone_list) do
766
+ [nil, home_phone, office_phone]
767
+ end
768
+
769
+ before do
770
+ person.phone_numbers = phone_list
771
+ person.save!
772
+ end
773
+
774
+ it "ignores the nil and persist the remaining items" do
775
+ reloaded = Person.find(person.id)
776
+ reloaded.phone_numbers.should eq([ home_phone, office_phone ])
777
+ end
778
+ end
779
+
780
+ context "when an embeds many relationship contains a nil in the middle of the list" do
781
+
782
+ let(:person) do
783
+ Person.create!
784
+ end
785
+
786
+ let(:phone_list) do
787
+ [home_phone, nil, office_phone]
788
+ end
789
+
790
+ before do
791
+ person.phone_numbers = phone_list
792
+ person.save!
793
+ end
794
+
795
+ it "ignores the nil and persist the remaining items" do
796
+ reloaded = Person.find(person.id)
797
+ reloaded.phone_numbers.should eq([ home_phone, office_phone ])
798
+ end
799
+ end
800
+
801
+ context "when an embeds many relationship contains a nil at the end of the list" do
802
+
803
+ let(:person) do
804
+ Person.create!
805
+ end
806
+
807
+ let(:phone_list) do
808
+ [home_phone, office_phone, nil]
809
+ end
810
+
811
+ before do
812
+ person.phone_numbers = phone_list
813
+ person.save!
814
+ end
815
+
816
+ it "ignores the nil and persist the remaining items" do
817
+ reloaded = Person.find(person.id)
818
+ reloaded.phone_numbers.should eq([ home_phone, office_phone ])
819
+ end
820
+ end
821
+ end
822
+
823
+ describe "appending to the embedded list" do
824
+
825
+ context "when appending a nil to the first position in an embedded list" do
826
+
827
+ let(:person) do
828
+ Person.create! phone_numbers: []
829
+ end
830
+
831
+ before do
832
+ person.phone_numbers << nil
833
+ person.phone_numbers << home_phone
834
+ person.phone_numbers << office_phone
835
+ person.save!
836
+ end
837
+
838
+ it "ignores the nil and persist the remaining items" do
839
+ reloaded = Person.find(person.id)
840
+ reloaded.phone_numbers.should eq(person.phone_numbers)
841
+ end
842
+ end
843
+
844
+ context "when appending a nil into the middle of an embedded list" do
845
+
846
+ let(:person) do
847
+ Person.create! phone_numbers: []
848
+ end
849
+
850
+ before do
851
+ person.phone_numbers << home_phone
852
+ person.phone_numbers << nil
853
+ person.phone_numbers << office_phone
854
+ person.save!
855
+ end
856
+
857
+ it "ignores the nil and persist the remaining items" do
858
+ reloaded = Person.find(person.id)
859
+ reloaded.phone_numbers.should eq(person.phone_numbers)
860
+ end
861
+ end
862
+
863
+ context "when appending a nil to the end of an embedded list" do
864
+
865
+ let(:person) do
866
+ Person.create! phone_numbers: []
867
+ end
868
+
869
+ before do
870
+ person.phone_numbers << home_phone
871
+ person.phone_numbers << office_phone
872
+ person.phone_numbers << nil
873
+ person.save!
874
+ end
875
+
876
+ it "ignores the nil and persist the remaining items" do
877
+ reloaded = Person.find(person.id)
878
+ reloaded.phone_numbers.should eq(person.phone_numbers)
879
+ end
880
+ end
881
+ end
882
+ end
883
+
884
+ context "when moving an embedded document from one parent to another" do
885
+
886
+ let!(:person_one) do
887
+ Person.create
888
+ end
889
+
890
+ let!(:person_two) do
891
+ Person.create
892
+ end
893
+
894
+ let!(:address) do
895
+ person_one.addresses.create(street: "Kudamm")
896
+ end
897
+
898
+ before do
899
+ person_two.addresses << address
900
+ end
901
+
902
+ it "adds the document to the new paarent" do
903
+ person_two.addresses.should eq([ address ])
904
+ end
905
+
906
+ it "sets the new parent on the document" do
907
+ address._parent.should eq(person_two)
908
+ end
909
+
910
+ context "when reloading the documents" do
911
+
912
+ before do
913
+ person_one.reload
914
+ person_two.reload
915
+ end
916
+
917
+ it "persists the change to the new parent" do
918
+ person_two.addresses.should eq([ address ])
919
+ end
920
+
921
+ it "keeps the address on the previous document" do
922
+ person_one.addresses.should eq([ address ])
923
+ end
924
+ end
925
+ end
926
+
927
+ context "when the relation has a default scope" do
928
+
929
+ let!(:person) do
930
+ Person.create
931
+ end
932
+
933
+ context "when the default scope is a sort" do
934
+
935
+ let(:cough) do
936
+ Symptom.new(name: "cough")
937
+ end
938
+
939
+ let(:headache) do
940
+ Symptom.new(name: "headache")
941
+ end
942
+
943
+ let(:nausea) do
944
+ Symptom.new(name: "nausea")
945
+ end
946
+
947
+ before do
948
+ person.symptoms.concat([ nausea, cough, headache ])
949
+ end
950
+
951
+ context "when accessing the relation" do
952
+
953
+ let(:symptoms) do
954
+ person.reload.symptoms
955
+ end
956
+
957
+ it "applies the default scope" do
958
+ symptoms.should eq([ cough, headache, nausea ])
959
+ end
960
+ end
961
+
962
+ context "when modifying the relation" do
963
+
964
+ let(:constipation) do
965
+ Symptom.new(name: "constipation")
966
+ end
967
+
968
+ before do
969
+ person.symptoms.push(constipation)
970
+ end
971
+
972
+ context "when reloading" do
973
+
974
+ let(:symptoms) do
975
+ person.reload.symptoms
976
+ end
977
+
978
+ it "applies the default scope" do
979
+ symptoms.should eq([ constipation, cough, headache, nausea ])
980
+ end
981
+ end
982
+ end
983
+
984
+ context "when unscoping the relation" do
985
+
986
+ let(:unscoped) do
987
+ person.reload.symptoms.unscoped
988
+ end
989
+
990
+ it "removes the default scope" do
991
+ unscoped.should eq([ nausea, cough, headache ])
992
+ end
993
+ end
994
+ end
995
+ end
996
+
997
+ context "when the embedded document has an array field" do
998
+
999
+ let!(:person) do
1000
+ Person.create
1001
+ end
1002
+
1003
+ let!(:video) do
1004
+ person.videos.create
1005
+ end
1006
+
1007
+ context "when saving the array on a persisted document" do
1008
+
1009
+ before do
1010
+ video.genres = [ "horror", "scifi" ]
1011
+ video.save
1012
+ end
1013
+
1014
+ it "sets the value" do
1015
+ video.genres.should eq([ "horror", "scifi" ])
1016
+ end
1017
+
1018
+ it "persists the value" do
1019
+ video.reload.genres.should eq([ "horror", "scifi" ])
1020
+ end
1021
+
1022
+ context "when reloading the parent" do
1023
+
1024
+ let!(:loaded_person) do
1025
+ Person.find(person.id)
1026
+ end
1027
+
1028
+ let!(:loaded_video) do
1029
+ loaded_person.videos.find(video.id)
1030
+ end
1031
+
1032
+ context "when writing a new array value" do
1033
+
1034
+ before do
1035
+ loaded_video.genres = [ "comedy" ]
1036
+ loaded_video.save
1037
+ end
1038
+
1039
+ it "sets the new value" do
1040
+ loaded_video.genres.should eq([ "comedy" ])
1041
+ end
1042
+
1043
+ it "persists the new value" do
1044
+ loaded_video.reload.genres.should eq([ "comedy" ])
1045
+ end
1046
+ end
1047
+ end
1048
+ end
1049
+ end
1050
+
1051
+ context "when adding a document" do
1052
+
1053
+ let(:person) do
1054
+ Person.new
1055
+ end
1056
+
1057
+ let(:address_one) do
1058
+ Address.new(street: "hobrecht")
1059
+ end
1060
+
1061
+ let(:first_add) do
1062
+ person.addresses.push(address_one)
1063
+ end
1064
+
1065
+ context "when chaining a second add" do
1066
+
1067
+ let(:address_two) do
1068
+ Address.new(street: "friedel")
1069
+ end
1070
+
1071
+ let(:result) do
1072
+ first_add.push(address_two)
1073
+ end
1074
+
1075
+ it "adds both documents" do
1076
+ result.should eq([ address_one, address_two ])
1077
+ end
1078
+ end
1079
+ end
1080
+
1081
+ context "when using dot notation in a criteria" do
1082
+
1083
+ let(:person) do
1084
+ Person.new
1085
+ end
1086
+
1087
+ let!(:address) do
1088
+ person.addresses.build(street: "hobrecht")
1089
+ end
1090
+
1091
+ let!(:location) do
1092
+ address.locations.build(number: 5)
1093
+ end
1094
+
1095
+ let(:criteria) do
1096
+ person.addresses.where("locations.number" => { "$gt" => 3 })
1097
+ end
1098
+
1099
+ it "allows the dot notation criteria" do
1100
+ criteria.should eq([ address ])
1101
+ end
1102
+ end
1103
+
1104
+ context "when updating multiple levels in one update" do
1105
+
1106
+ let!(:person) do
1107
+ Person.create(
1108
+ addresses: [
1109
+ { locations: [{ name: "home" }]}
1110
+ ]
1111
+ )
1112
+ end
1113
+
1114
+ context "when updating with hashes" do
1115
+
1116
+ let(:from_db) do
1117
+ Person.find(person.id)
1118
+ end
1119
+
1120
+ before do
1121
+ from_db.update_attributes(
1122
+ addresses: [
1123
+ { locations: [{ name: "work" }]}
1124
+ ]
1125
+ )
1126
+ end
1127
+
1128
+ let(:updated) do
1129
+ person.reload.addresses.first.locations.first
1130
+ end
1131
+
1132
+ it "updates the nested document" do
1133
+ updated.name.should eq("work")
1134
+ end
1135
+ end
1136
+ end
1137
+
1138
+ context "when pushing with a before_add callback" do
1139
+
1140
+ let(:artist) do
1141
+ Artist.new
1142
+ end
1143
+
1144
+ let(:song) do
1145
+ Song.new
1146
+ end
1147
+
1148
+ context "when no errors are raised" do
1149
+
1150
+ before do
1151
+ artist.songs << song
1152
+ end
1153
+
1154
+ it "executes the callback" do
1155
+ artist.before_add_called.should eq true
1156
+ end
1157
+
1158
+ it "executes the callback as proc" do
1159
+ song.before_add_called.should eq true
1160
+ end
1161
+
1162
+ it "adds the document to the relation" do
1163
+ artist.songs.should eq([song])
1164
+ end
1165
+ end
1166
+
1167
+ context "with errors" do
1168
+
1169
+ before do
1170
+ artist.should_receive(:before_add_song).and_raise
1171
+ end
1172
+
1173
+ it "does not add the document to the relation" do
1174
+ expect {
1175
+ artist.songs << song
1176
+ }.to raise_error
1177
+ artist.songs.should be_empty
1178
+ end
1179
+ end
1180
+ end
1181
+
1182
+ context "when pushing with an after_add callback" do
1183
+
1184
+ let(:artist) do
1185
+ Artist.new
1186
+ end
1187
+
1188
+ let(:label) do
1189
+ Label.new
1190
+ end
1191
+
1192
+ it "executes the callback" do
1193
+ artist.labels << label
1194
+ artist.after_add_called.should eq true
1195
+ end
1196
+
1197
+ context "when errors are raised" do
1198
+
1199
+ before do
1200
+ artist.should_receive(:after_add_label).and_raise
1201
+ end
1202
+
1203
+ it "adds the document to the relation" do
1204
+ expect {
1205
+ artist.labels << label
1206
+ }.to raise_error
1207
+ artist.labels.should eq([ label ])
1208
+ end
1209
+ end
1210
+ end
1211
+ end
1212
+
1213
+ end