mongoid_monkey 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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