mongoid 0.8.10 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,6 +21,7 @@ end
21
21
 
22
22
  class Person < Mongoid::Document
23
23
  include Mongoid::Timestamps
24
+
24
25
  field :title
25
26
  field :terms, :type => Boolean
26
27
  field :age, :type => Integer, :default => 100
@@ -28,8 +29,10 @@ class Person < Mongoid::Document
28
29
  field :mixed_drink, :type => MixedDrink
29
30
  field :employer_id
30
31
  field :lunch_time, :type => Time
32
+
31
33
  has_many :addresses
32
34
  has_many :phone_numbers, :class_name => "Phone"
35
+
33
36
  has_one :name
34
37
  has_one :pet, :class_name => "Animal"
35
38
 
@@ -42,6 +45,19 @@ class Person < Mongoid::Document
42
45
  def employer=(emp)
43
46
  self.employer_id = emp.id
44
47
  end
48
+
49
+ class << self
50
+ def accepted
51
+ criteria.where(:terms => true)
52
+ end
53
+ def knight
54
+ criteria.where(:title => "Sir")
55
+ end
56
+ def old
57
+ criteria.where(:age => { "$gt" => 50 })
58
+ end
59
+ end
60
+
45
61
  end
46
62
 
47
63
  class Employer
@@ -3,7 +3,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "/../../spec_helper.r
3
3
  describe Mongoid::Criteria do
4
4
 
5
5
  before do
6
- @criteria = Mongoid::Criteria.new(:all)
6
+ @criteria = Mongoid::Criteria.new(Person)
7
7
  end
8
8
 
9
9
  describe "#aggregate" do
@@ -12,7 +12,7 @@ describe Mongoid::Criteria do
12
12
 
13
13
  before do
14
14
  @reduce = "function(obj, prev) { prev.count++; }"
15
- @criteria = Mongoid::Criteria.new(:all, Person)
15
+ @criteria = Mongoid::Criteria.new(Person)
16
16
  @collection = mock
17
17
  Person.expects(:collection).returns(@collection)
18
18
  end
@@ -54,134 +54,147 @@ describe Mongoid::Criteria do
54
54
 
55
55
  end
56
56
 
57
- describe "#count" do
57
+ describe "#collect" do
58
58
 
59
- context "when criteria has not been executed" do
59
+ context "filtering" do
60
60
 
61
61
  before do
62
- @criteria.instance_variable_set(:@count, 34)
62
+ @collection = mock
63
+ Person.expects(:collection).returns(@collection)
64
+ @criteria = Mongoid::Criteria.new(Person).extras(:page => 1, :per_page => 20)
65
+ @collection.expects(:find).with(@criteria.selector, @criteria.options).returns([])
63
66
  end
64
67
 
65
- it "returns a count from the cursor" do
66
- @criteria.count.should == 34
68
+ it "filters out unused params" do
69
+ @criteria.collect
70
+ @criteria.options[:page].should be_nil
71
+ @criteria.options[:per_page].should be_nil
67
72
  end
68
73
 
69
74
  end
70
75
 
71
- context "when criteria has been executed" do
76
+ context "when type is :all" do
72
77
 
73
78
  before do
74
- @criteria = Mongoid::Criteria.new(:all, Person)
75
- @selector = { :test => "Testing" }
76
- @criteria.where(@selector)
77
79
  @collection = mock
78
- @cursor = mock
79
80
  Person.expects(:collection).returns(@collection)
81
+ @criteria = Mongoid::Criteria.new(Person).extras(:page => 1, :per_page => 20)
82
+ @cursor = stub(:count => 44, :collect => [])
83
+ @collection.expects(:find).with(@criteria.selector, @criteria.options).returns(@cursor)
80
84
  end
81
85
 
82
- it "returns the count from the cursor without creating the documents" do
83
- @collection.expects(:find).with(@selector, {}).returns(@cursor)
84
- @cursor.expects(:count).returns(10)
85
- @criteria.count.should == 10
86
+ it "adds the count instance variable" do
87
+ @criteria.collect.should == []
88
+ @criteria.count.should == 44
86
89
  end
87
90
 
88
91
  end
89
92
 
90
- end
93
+ context "when type is :first" do
91
94
 
92
- describe "#excludes" do
93
95
 
94
- it "adds the $ne query to the selector" do
95
- @criteria.excludes(:title => "Bad Title", :text => "Bad Text")
96
- @criteria.selector.should == { :title => { "$ne" => "Bad Title"}, :text => { "$ne" => "Bad Text" } }
97
96
  end
98
97
 
99
- it "returns self" do
100
- @criteria.excludes(:title => "Bad").should == @criteria
98
+ context "when type is not :first" do
99
+
100
+ it "calls find on the collection with the selector and options" do
101
+ criteria = Mongoid::Criteria.new(Person)
102
+ collection = mock
103
+ Person.expects(:collection).returns(collection)
104
+ collection.expects(:find).with(@criteria.selector, @criteria.options).returns([])
105
+ criteria.collect.should == []
106
+ end
107
+
101
108
  end
102
109
 
103
110
  end
104
111
 
105
- describe "#execute" do
112
+ describe "#count" do
106
113
 
107
- context "filtering" do
114
+ context "when criteria has not been executed" do
108
115
 
109
116
  before do
110
- @collection = mock
111
- Person.expects(:collection).returns(@collection)
112
- @criteria = Mongoid::Criteria.new(:all).extras(:page => 1, :per_page => 20)
113
- @collection.expects(:find).with(@criteria.selector, @criteria.options).returns([])
117
+ @criteria.instance_variable_set(:@count, 34)
114
118
  end
115
119
 
116
- it "filters out unused params" do
117
- @criteria.execute(Person)
118
- @criteria.options[:page].should be_nil
119
- @criteria.options[:per_page].should be_nil
120
+ it "returns a count from the cursor" do
121
+ @criteria.count.should == 34
120
122
  end
121
123
 
122
124
  end
123
125
 
124
- context "when type is :all" do
126
+ context "when criteria has been executed" do
125
127
 
126
128
  before do
129
+ @criteria = Mongoid::Criteria.new(Person)
130
+ @selector = { :test => "Testing" }
131
+ @criteria.where(@selector)
127
132
  @collection = mock
133
+ @cursor = mock
128
134
  Person.expects(:collection).returns(@collection)
129
- @criteria = Mongoid::Criteria.new(:all).extras(:page => 1, :per_page => 20)
130
- @cursor = stub(:count => 44, :collect => [])
131
- @collection.expects(:find).with(@criteria.selector, @criteria.options).returns(@cursor)
132
135
  end
133
136
 
134
- it "adds the count instance variable" do
135
- @criteria.execute(Person).should == []
136
- @criteria.count.should == 44
137
+ it "returns the count from the cursor without creating the documents" do
138
+ @collection.expects(:find).with(@selector, {}).returns(@cursor)
139
+ @cursor.expects(:count).returns(10)
140
+ @criteria.count.should == 10
137
141
  end
138
142
 
139
143
  end
140
144
 
141
- context "when type is :first" do
145
+ end
142
146
 
143
- context "when documents exist" do
147
+ describe "#each" do
144
148
 
145
- before do
146
- @collection = mock
147
- Person.expects(:collection).returns(@collection)
148
- @collection.expects(:find_one).with(@criteria.selector, @criteria.options).returns({ :title => "Sir" })
149
- end
149
+ before do
150
+ @criteria.where(:title => "Sir")
151
+ @collection = stub
152
+ @person = Person.new(:title => "Sir")
153
+ @cursor = stub(:count => 10, :collect => [@person])
154
+ end
150
155
 
151
- it "calls find on the collection with the selector and options" do
152
- criteria = Mongoid::Criteria.new(:first)
153
- criteria.execute(Person).should be_a_kind_of(Person)
154
- end
156
+ context "when the criteria has not been executed" do
155
157
 
158
+ before do
159
+ Person.expects(:collection).returns(@collection)
160
+ @collection.expects(:find).with({ :title => "Sir" }, {}).returns(@cursor)
156
161
  end
157
162
 
158
- context "when no documents exist" do
159
-
160
- before do
161
- @collection = mock
162
- Person.expects(:collection).returns(@collection)
163
- @collection.expects(:find_one).with(@criteria.selector, @criteria.options).returns(nil)
163
+ it "executes the criteria" do
164
+ @criteria.each do |person|
165
+ person.should == @person
164
166
  end
167
+ end
165
168
 
166
- it "returns nil" do
167
- criteria = Mongoid::Criteria.new(:first)
168
- criteria.execute(Person).should be_nil
169
- end
169
+ end
170
170
 
171
+ context "when the criteria has been executed" do
172
+
173
+ before do
174
+ Person.expects(:collection).returns(@collection)
175
+ @collection.expects(:find).with({ :title => "Sir" }, {}).returns(@cursor)
176
+ end
177
+
178
+ it "calls each on the existing results" do
179
+ @criteria.each
180
+ @criteria.each do |person|
181
+ person.should == @person
182
+ end
171
183
  end
172
184
 
173
185
  end
174
186
 
175
- context "when type is not :first" do
187
+ end
176
188
 
177
- it "calls find on the collection with the selector and options" do
178
- criteria = Mongoid::Criteria.new(:all)
179
- collection = mock
180
- Person.expects(:collection).returns(collection)
181
- collection.expects(:find).with(@criteria.selector, @criteria.options).returns([])
182
- criteria.execute(Person).should == []
183
- end
189
+ describe "#excludes" do
184
190
 
191
+ it "adds the $ne query to the selector" do
192
+ @criteria.excludes(:title => "Bad Title", :text => "Bad Text")
193
+ @criteria.selector.should == { :title => { "$ne" => "Bad Title"}, :text => { "$ne" => "Bad Text" } }
194
+ end
195
+
196
+ it "returns self" do
197
+ @criteria.excludes(:title => "Bad").should == @criteria
185
198
  end
186
199
 
187
200
  end
@@ -242,7 +255,7 @@ describe Mongoid::Criteria do
242
255
 
243
256
  before do
244
257
  @reduce = "function(obj, prev) { prev.group.push(obj); }"
245
- @criteria = Mongoid::Criteria.new(:all, Person)
258
+ @criteria = Mongoid::Criteria.new(Person)
246
259
  @collection = mock
247
260
  Person.expects(:collection).returns(@collection)
248
261
  end
@@ -299,6 +312,56 @@ describe Mongoid::Criteria do
299
312
 
300
313
  end
301
314
 
315
+ describe "#last" do
316
+
317
+ context "when documents exist" do
318
+
319
+ before do
320
+ @collection = mock
321
+ Person.expects(:collection).returns(@collection)
322
+ @collection.expects(:find_one).with(@criteria.selector, { :sort => [[:title, :desc]] }).returns({ :title => "Sir" })
323
+ end
324
+
325
+ it "calls find on the collection with the selector and sort options reversed" do
326
+ criteria = Mongoid::Criteria.new(Person)
327
+ criteria.order_by([[:title, :asc]])
328
+ criteria.last.should be_a_kind_of(Person)
329
+ end
330
+
331
+ end
332
+
333
+ context "when no documents exist" do
334
+
335
+ before do
336
+ @collection = mock
337
+ Person.expects(:collection).returns(@collection)
338
+ @collection.expects(:find_one).with(@criteria.selector, { :sort => [[:_id, :desc]] }).returns(nil)
339
+ end
340
+
341
+ it "returns nil" do
342
+ criteria = Mongoid::Criteria.new(Person)
343
+ criteria.last.should be_nil
344
+ end
345
+
346
+ end
347
+
348
+ context "when no sorting options provided" do
349
+
350
+ before do
351
+ @collection = mock
352
+ Person.expects(:collection).returns(@collection)
353
+ @collection.expects(:find_one).with(@criteria.selector, { :sort => [[:_id, :desc]] }).returns({ :title => "Sir" })
354
+ end
355
+
356
+ it "defaults to sort by id" do
357
+ criteria = Mongoid::Criteria.new(Person)
358
+ criteria.last
359
+ end
360
+
361
+ end
362
+
363
+ end
364
+
302
365
  describe "#limit" do
303
366
 
304
367
  context "when value provided" do
@@ -325,6 +388,116 @@ describe Mongoid::Criteria do
325
388
 
326
389
  end
327
390
 
391
+ describe "#merge" do
392
+
393
+ before do
394
+ @criteria.where(:title => "Sir", :age => 30).skip(40).limit(20)
395
+ end
396
+
397
+ context "with another criteria" do
398
+
399
+ context "when the other has a selector and options" do
400
+
401
+ before do
402
+ @other = Mongoid::Criteria.new(Person)
403
+ @other.where(:name => "Chloe").order_by([[:name, :asc]])
404
+ @selector = { :title => "Sir", :age => 30, :name => "Chloe" }
405
+ @options = { :skip => 40, :limit => 20, :sort => [[:name, :asc]] }
406
+ end
407
+
408
+ it "merges the selector and options hashes together" do
409
+ @criteria.merge(@other)
410
+ @criteria.selector.should == @selector
411
+ @criteria.options.should == @options
412
+ end
413
+
414
+ end
415
+
416
+ context "when the other has no selector or options" do
417
+
418
+ before do
419
+ @other = Mongoid::Criteria.new(Person)
420
+ @selector = { :title => "Sir", :age => 30 }
421
+ @options = { :skip => 40, :limit => 20 }
422
+ end
423
+
424
+ it "merges the selector and options hashes together" do
425
+ @criteria.merge(@other)
426
+ @criteria.selector.should == @selector
427
+ @criteria.options.should == @options
428
+ end
429
+ end
430
+
431
+ end
432
+
433
+ context "with a hash" do
434
+
435
+ context "when hash has values" do
436
+
437
+ before do
438
+ @hash = { :conditions => { :name => "Rebecca" }, :sort => [[:name, :desc]] }
439
+ @selector = { :title => "Sir", :age => 30, :name => "Rebecca" }
440
+ @options = { :skip => 40, :limit => 20, :sort => [[:name, :desc]] }
441
+ @criteria.merge(@hash)
442
+ end
443
+
444
+ it "merges the conditions with the selector" do
445
+ @criteria.selector.should == @selector
446
+ end
447
+
448
+ it "merges all valid other values into the options" do
449
+ @criteria.options.should == @options
450
+ end
451
+
452
+ end
453
+
454
+ context "when hash is empty" do
455
+
456
+ before do
457
+ @hash = {}
458
+ @selector = { :title => "Sir", :age => 30 }
459
+ @options = { :skip => 40, :limit => 20 }
460
+ end
461
+
462
+ it "merges nothing" do
463
+ @criteria.merge(@hash)
464
+ @criteria.selector.should == @selector
465
+ @criteria.options.should == @options
466
+ end
467
+
468
+ end
469
+
470
+ end
471
+
472
+ end
473
+
474
+ describe "#method_missing" do
475
+
476
+ before do
477
+ @criteria = Mongoid::Criteria.new(Person)
478
+ @criteria.where(:title => "Sir")
479
+ end
480
+
481
+ it "merges the criteria with the next one" do
482
+ @new_criteria = @criteria.accepted
483
+ @new_criteria.selector.should == { :title => "Sir", :terms => true }
484
+ end
485
+
486
+ context "chaining more than one scope" do
487
+
488
+ before do
489
+ @criteria = Person.accepted.old.knight
490
+ end
491
+
492
+ it "returns the final merged criteria" do
493
+ @criteria.selector.should ==
494
+ { :title => "Sir", :terms => true, :age => { "$gt" => 50 } }
495
+ end
496
+
497
+ end
498
+
499
+ end
500
+
328
501
  describe "#not_in" do
329
502
 
330
503
  it "adds the exclusion to the selector" do
@@ -343,7 +516,7 @@ describe Mongoid::Criteria do
343
516
  context "when the per_page option exists" do
344
517
 
345
518
  before do
346
- @criteria = Mongoid::Criteria.new(:all).extras({ :per_page => 20, :page => 3 })
519
+ @criteria = Mongoid::Criteria.new(Person).extras({ :per_page => 20, :page => 3 })
347
520
  end
348
521
 
349
522
  it "returns the per_page option" do
@@ -355,7 +528,7 @@ describe Mongoid::Criteria do
355
528
  context "when the skip option exists" do
356
529
 
357
530
  before do
358
- @criteria = Mongoid::Criteria.new(:all).extras({ :skip => 20 })
531
+ @criteria = Mongoid::Criteria.new(Person).extras({ :skip => 20 })
359
532
  end
360
533
 
361
534
  it "returns the skip option" do
@@ -369,7 +542,7 @@ describe Mongoid::Criteria do
369
542
  context "when page option exists" do
370
543
 
371
544
  before do
372
- @criteria = Mongoid::Criteria.new(:all).extras({ :page => 2 })
545
+ @criteria = Mongoid::Criteria.new(Person).extras({ :page => 2 })
373
546
  end
374
547
 
375
548
  it "adds the skip option to the options and returns it" do
@@ -382,7 +555,7 @@ describe Mongoid::Criteria do
382
555
  context "when page option does not exist" do
383
556
 
384
557
  before do
385
- @criteria = Mongoid::Criteria.new(:all)
558
+ @criteria = Mongoid::Criteria.new(Person)
386
559
  end
387
560
 
388
561
  it "returns nil" do
@@ -396,6 +569,40 @@ describe Mongoid::Criteria do
396
569
 
397
570
  end
398
571
 
572
+ describe "#one" do
573
+
574
+ context "when documents exist" do
575
+
576
+ before do
577
+ @collection = mock
578
+ Person.expects(:collection).returns(@collection)
579
+ @collection.expects(:find_one).with(@criteria.selector, @criteria.options).returns({ :title => "Sir" })
580
+ end
581
+
582
+ it "calls find on the collection with the selector and options" do
583
+ criteria = Mongoid::Criteria.new(Person)
584
+ criteria.one.should be_a_kind_of(Person)
585
+ end
586
+
587
+ end
588
+
589
+ context "when no documents exist" do
590
+
591
+ before do
592
+ @collection = mock
593
+ Person.expects(:collection).returns(@collection)
594
+ @collection.expects(:find_one).with(@criteria.selector, @criteria.options).returns(nil)
595
+ end
596
+
597
+ it "returns nil" do
598
+ criteria = Mongoid::Criteria.new(Person)
599
+ criteria.one.should be_nil
600
+ end
601
+
602
+ end
603
+
604
+ end
605
+
399
606
  describe "#order_by" do
400
607
 
401
608
  context "when field names and direction specified" do
@@ -418,7 +625,7 @@ describe Mongoid::Criteria do
418
625
  context "when the page option exists" do
419
626
 
420
627
  before do
421
- @criteria = Mongoid::Criteria.new(:all).extras({ :page => 5 })
628
+ @criteria = Mongoid::Criteria.new(Person).extras({ :page => 5 })
422
629
  end
423
630
 
424
631
  it "returns the page option" do
@@ -430,7 +637,7 @@ describe Mongoid::Criteria do
430
637
  context "when the page option does not exist" do
431
638
 
432
639
  before do
433
- @criteria = Mongoid::Criteria.new(:all)
640
+ @criteria = Mongoid::Criteria.new(Person)
434
641
  end
435
642
 
436
643
  it "returns 1" do
@@ -463,7 +670,7 @@ describe Mongoid::Criteria do
463
670
  context "when the per_page option exists" do
464
671
 
465
672
  before do
466
- @criteria = Mongoid::Criteria.new(:all).extras({ :per_page => 10 })
673
+ @criteria = Mongoid::Criteria.new(Person).extras({ :per_page => 10 })
467
674
  end
468
675
 
469
676
  it "returns the per_page option" do
@@ -475,7 +682,7 @@ describe Mongoid::Criteria do
475
682
  context "when the per_page option does not exist" do
476
683
 
477
684
  before do
478
- @criteria = Mongoid::Criteria.new(:all)
685
+ @criteria = Mongoid::Criteria.new(Person)
479
686
  end
480
687
 
481
688
  it "returns 1" do
@@ -542,34 +749,35 @@ describe Mongoid::Criteria do
542
749
 
543
750
  context "with a single argument" do
544
751
 
545
- it "creates a criteria for an object id" do
546
- id = Mongo::ObjectID.new.to_s
547
- criteria = Mongoid::Criteria.translate(id)
548
- criteria.selector.should == { :_id => id }
752
+ before do
753
+ @id = Mongo::ObjectID.new.to_s
754
+ @document = stub
755
+ @criteria = mock
756
+ Mongoid::Criteria.expects(:new).returns(@criteria)
757
+ @criteria.expects(:id).with(@id).returns(@criteria)
758
+ @criteria.expects(:one).returns(@document)
549
759
  end
550
760
 
551
761
  it "creates a criteria for a string" do
552
- id = Mongo::ObjectID.new.to_s
553
- criteria = Mongoid::Criteria.translate(id)
554
- criteria.selector.should == { :_id => id }
762
+ Mongoid::Criteria.translate(Person, @id)
555
763
  end
556
764
 
557
765
  end
558
766
 
559
767
  context "multiple arguments" do
560
768
 
561
- context "when :first, :conditions => {}" do
769
+ context "when Person, :conditions => {}" do
562
770
 
563
771
  before do
564
- @criteria = Mongoid::Criteria.translate(:first, :conditions => { :title => "Test" })
772
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
565
773
  end
566
774
 
567
775
  it "returns a criteria with a selector from the conditions" do
568
776
  @criteria.selector.should == { :title => "Test" }
569
777
  end
570
778
 
571
- it "returns a criteria with type :first" do
572
- @criteria.type.should == :first
779
+ it "returns a criteria with klass Person" do
780
+ @criteria.klass.should == Person
573
781
  end
574
782
 
575
783
  end
@@ -577,15 +785,15 @@ describe Mongoid::Criteria do
577
785
  context "when :all, :conditions => {}" do
578
786
 
579
787
  before do
580
- @criteria = Mongoid::Criteria.translate(:all, :conditions => { :title => "Test" })
788
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
581
789
  end
582
790
 
583
791
  it "returns a criteria with a selector from the conditions" do
584
792
  @criteria.selector.should == { :title => "Test" }
585
793
  end
586
794
 
587
- it "returns a criteria with type :all" do
588
- @criteria.type.should == :all
795
+ it "returns a criteria with klass Person" do
796
+ @criteria.klass.should == Person
589
797
  end
590
798
 
591
799
  end
@@ -593,23 +801,22 @@ describe Mongoid::Criteria do
593
801
  context "when :last, :conditions => {}" do
594
802
 
595
803
  before do
596
- @criteria = Mongoid::Criteria.translate(:last, :conditions => { :title => "Test" })
804
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
597
805
  end
598
806
 
599
807
  it "returns a criteria with a selector from the conditions" do
600
808
  @criteria.selector.should == { :title => "Test" }
601
809
  end
602
810
 
603
- it "returns a criteria with type :last" do
604
- @criteria.type.should == :last
811
+ it "returns a criteria with klass Person" do
812
+ @criteria.klass.should == Person
605
813
  end
606
-
607
814
  end
608
815
 
609
816
  context "when options are provided" do
610
817
 
611
818
  before do
612
- @criteria = Mongoid::Criteria.translate(:last, :conditions => { :title => "Test" }, :skip => 10)
819
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" }, :skip => 10)
613
820
  end
614
821
 
615
822
  it "adds the criteria and the options" do