mongoid 1.0.6 → 1.1.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.
- data/HISTORY +39 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongoid.rb +3 -1
- data/lib/mongoid/associations.rb +5 -5
- data/lib/mongoid/associations/has_many.rb +8 -2
- data/lib/mongoid/associations/has_many_related.rb +10 -4
- data/lib/mongoid/attributes.rb +19 -13
- data/lib/mongoid/commands.rb +12 -6
- data/lib/mongoid/commands/create.rb +2 -2
- data/lib/mongoid/commands/delete_all.rb +1 -1
- data/lib/mongoid/commands/save.rb +2 -2
- data/lib/mongoid/components.rb +1 -0
- data/lib/mongoid/contexts.rb +4 -0
- data/lib/mongoid/contexts/enumerable.rb +105 -0
- data/lib/mongoid/contexts/mongo.rb +228 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +42 -191
- data/lib/mongoid/document.rb +19 -13
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/array/accessors.rb +3 -1
- data/lib/mongoid/extensions/float/conversions.rb +1 -1
- data/lib/mongoid/extensions/hash/accessors.rb +1 -1
- data/lib/mongoid/extensions/integer/conversions.rb +1 -0
- data/lib/mongoid/fields.rb +6 -5
- data/lib/mongoid/matchers.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +20 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/lib/mongoid/scope.rb +17 -1
- data/mongoid.gemspec +51 -5
- data/spec/integration/mongoid/associations_spec.rb +67 -5
- data/spec/integration/mongoid/attributes_spec.rb +22 -0
- data/spec/integration/mongoid/commands_spec.rb +51 -12
- data/spec/integration/mongoid/criteria_spec.rb +3 -3
- data/spec/integration/mongoid/document_spec.rb +8 -8
- data/spec/integration/mongoid/finders_spec.rb +1 -1
- data/spec/integration/mongoid/inheritance_spec.rb +6 -0
- data/spec/integration/mongoid/named_scope_spec.rb +1 -1
- data/spec/spec_helper.rb +47 -6
- data/spec/unit/mongoid/associations/has_many_related_spec.rb +42 -0
- data/spec/unit/mongoid/associations/has_many_spec.rb +40 -1
- data/spec/unit/mongoid/attributes_spec.rb +1 -1
- data/spec/unit/mongoid/commands/create_spec.rb +3 -3
- data/spec/unit/mongoid/commands/delete_all_spec.rb +2 -2
- data/spec/unit/mongoid/commands/save_spec.rb +2 -2
- data/spec/unit/mongoid/commands_spec.rb +12 -12
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +208 -0
- data/spec/unit/mongoid/contexts/mongo_spec.rb +370 -0
- data/spec/unit/mongoid/criteria_spec.rb +182 -21
- data/spec/unit/mongoid/extensions/array/accessors_spec.rb +9 -9
- data/spec/unit/mongoid/extensions/date/conversions_spec.rb +2 -1
- data/spec/unit/mongoid/extensions/float/conversions_spec.rb +4 -4
- data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +1 -1
- data/spec/unit/mongoid/fields_spec.rb +3 -3
- data/spec/unit/mongoid/identity_spec.rb +2 -2
- data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
- data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
- data/spec/unit/mongoid/matchers_spec.rb +329 -0
- data/spec/unit/mongoid/scope_spec.rb +70 -0
- data/spec/unit/mongoid/timestamps_spec.rb +2 -2
- metadata +50 -4
@@ -4,7 +4,7 @@ describe Mongoid::Associations::HasMany do
|
|
4
4
|
|
5
5
|
before do
|
6
6
|
@attributes = { :addresses => [
|
7
|
-
{ :_id => "street-1", :street => "Street 1" },
|
7
|
+
{ :_id => "street-1", :street => "Street 1", :state => "CA" },
|
8
8
|
{ :_id => "street-2", :street => "Street 2" } ] }
|
9
9
|
@document = stub(:attributes => @attributes, :add_observer => true, :update => true)
|
10
10
|
end
|
@@ -322,6 +322,45 @@ describe Mongoid::Associations::HasMany do
|
|
322
322
|
|
323
323
|
end
|
324
324
|
|
325
|
+
describe "#method_missing" do
|
326
|
+
|
327
|
+
context "when the association class has a criteria class method" do
|
328
|
+
|
329
|
+
before do
|
330
|
+
@association = Mongoid::Associations::HasMany.new(
|
331
|
+
@document,
|
332
|
+
Mongoid::Associations::Options.new(:name => :addresses)
|
333
|
+
)
|
334
|
+
end
|
335
|
+
|
336
|
+
it "returns the criteria" do
|
337
|
+
@association.california.should be_a_kind_of(Mongoid::Criteria)
|
338
|
+
end
|
339
|
+
|
340
|
+
it "sets the documents on the criteria" do
|
341
|
+
criteria = @association.california
|
342
|
+
criteria.documents.should == @association.entries
|
343
|
+
end
|
344
|
+
|
345
|
+
it "returns the scoped documents" do
|
346
|
+
addresses = @association.california
|
347
|
+
addresses.size.should == 1
|
348
|
+
addresses.first.should be_a_kind_of(Address)
|
349
|
+
addresses.first.state.should == "CA"
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
353
|
+
|
354
|
+
context "when no class method exists" do
|
355
|
+
|
356
|
+
it "delegates to the array" do
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
|
325
364
|
describe "#push" do
|
326
365
|
|
327
366
|
before do
|
@@ -9,19 +9,19 @@ describe Mongoid::Commands::Create do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "executes a save command" do
|
12
|
-
Mongoid::Commands::Save.expects(:execute).with(@document, true).returns(@document)
|
12
|
+
Mongoid::Commands::Save.expects(:execute).with(@document, true, false).returns(@document)
|
13
13
|
Mongoid::Commands::Create.execute(@document)
|
14
14
|
end
|
15
15
|
|
16
16
|
it "runs the before and after create callbacks" do
|
17
17
|
@document.expects(:run_callbacks).with(:before_create)
|
18
|
-
Mongoid::Commands::Save.expects(:execute).with(@document, true).returns(@document)
|
18
|
+
Mongoid::Commands::Save.expects(:execute).with(@document, true, false).returns(@document)
|
19
19
|
@document.expects(:run_callbacks).with(:after_create)
|
20
20
|
Mongoid::Commands::Create.execute(@document)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "returns the document" do
|
24
|
-
Mongoid::Commands::Save.expects(:execute).with(@document, true).returns(@document)
|
24
|
+
Mongoid::Commands::Save.expects(:execute).with(@document, true, false).returns(@document)
|
25
25
|
Mongoid::Commands::Create.execute(@document).should == @document
|
26
26
|
end
|
27
27
|
|
@@ -33,7 +33,7 @@ describe Mongoid::Commands::DeleteAll do
|
|
33
33
|
|
34
34
|
it "drops the collection" do
|
35
35
|
@klass.expects(:collection).returns(@collection)
|
36
|
-
@collection.expects(:
|
36
|
+
@collection.expects(:remove).with(:_type => "Person")
|
37
37
|
Mongoid::Commands::DeleteAll.execute(@klass)
|
38
38
|
end
|
39
39
|
|
@@ -47,7 +47,7 @@ describe Mongoid::Commands::DeleteAll do
|
|
47
47
|
|
48
48
|
it "drops the collection" do
|
49
49
|
@klass.expects(:collection).returns(@collection)
|
50
|
-
@collection.expects(:
|
50
|
+
@collection.expects(:remove).with(:_type => "Person")
|
51
51
|
Mongoid::Commands::DeleteAll.execute(@klass, {})
|
52
52
|
end
|
53
53
|
|
@@ -39,7 +39,7 @@ describe Mongoid::Commands::Save do
|
|
39
39
|
context "when the document has a parent" do
|
40
40
|
|
41
41
|
it "executes a save on the parent" do
|
42
|
-
@parent_collection.expects(:save).with(@parent.attributes)
|
42
|
+
@parent_collection.expects(:save).with(@parent.attributes, :safe => false)
|
43
43
|
Mongoid::Commands::Save.execute(@document)
|
44
44
|
end
|
45
45
|
|
@@ -52,7 +52,7 @@ describe Mongoid::Commands::Save do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it "calls save on the document collection" do
|
55
|
-
@doc_collection.expects(:save).with(@document.attributes)
|
55
|
+
@doc_collection.expects(:save).with(@document.attributes, :safe => false)
|
56
56
|
Mongoid::Commands::Save.execute(@document)
|
57
57
|
end
|
58
58
|
|
@@ -27,7 +27,7 @@ describe Mongoid::Commands do
|
|
27
27
|
describe "#save" do
|
28
28
|
|
29
29
|
it "delegates to the Save command" do
|
30
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
30
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, false).returns(true)
|
31
31
|
@person.save
|
32
32
|
end
|
33
33
|
|
@@ -38,13 +38,13 @@ describe Mongoid::Commands do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
it "delegates to the save command" do
|
41
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
41
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, false).returns(true)
|
42
42
|
@person.save
|
43
43
|
end
|
44
44
|
|
45
45
|
it "runs the before and after create callbacks" do
|
46
46
|
@person.expects(:run_callbacks).with(:before_create)
|
47
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
47
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, false).returns(true)
|
48
48
|
@person.expects(:run_callbacks).with(:after_create)
|
49
49
|
@person.save
|
50
50
|
end
|
@@ -58,7 +58,7 @@ describe Mongoid::Commands do
|
|
58
58
|
end
|
59
59
|
|
60
60
|
it "passes the validate param to the command" do
|
61
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, false).returns(true)
|
61
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, false, false).returns(true)
|
62
62
|
@person.save(false)
|
63
63
|
end
|
64
64
|
|
@@ -71,7 +71,7 @@ describe Mongoid::Commands do
|
|
71
71
|
context "when validation passes" do
|
72
72
|
|
73
73
|
it "it returns the person" do
|
74
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
74
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(true)
|
75
75
|
@person.save!
|
76
76
|
end
|
77
77
|
|
@@ -80,7 +80,7 @@ describe Mongoid::Commands do
|
|
80
80
|
context "when validation fails" do
|
81
81
|
|
82
82
|
it "it raises an error" do
|
83
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(false)
|
83
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(false)
|
84
84
|
lambda { @person.save! }.should raise_error
|
85
85
|
end
|
86
86
|
|
@@ -93,14 +93,14 @@ describe Mongoid::Commands do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
it "delegates to the save command" do
|
96
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
96
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(true)
|
97
97
|
@person.save!
|
98
98
|
end
|
99
99
|
|
100
100
|
context "when validation fails" do
|
101
101
|
|
102
102
|
it "it raises an error " do
|
103
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(false)
|
103
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(false)
|
104
104
|
lambda { @person.save! }.should raise_error
|
105
105
|
end
|
106
106
|
|
@@ -108,7 +108,7 @@ describe Mongoid::Commands do
|
|
108
108
|
|
109
109
|
it "runs the before and after create callbacks" do
|
110
110
|
@person.expects(:run_callbacks).with(:before_create)
|
111
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
111
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(true)
|
112
112
|
@person.expects(:run_callbacks).with(:after_create)
|
113
113
|
@person.save!
|
114
114
|
end
|
@@ -120,7 +120,7 @@ describe Mongoid::Commands do
|
|
120
120
|
describe "#update_attributes" do
|
121
121
|
|
122
122
|
it "delegates to the Save command" do
|
123
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
123
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, false).returns(true)
|
124
124
|
@person.update_attributes({})
|
125
125
|
end
|
126
126
|
|
@@ -131,7 +131,7 @@ describe Mongoid::Commands do
|
|
131
131
|
context "when validation passes" do
|
132
132
|
|
133
133
|
it "it returns the person" do
|
134
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(true)
|
134
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, false).returns(true)
|
135
135
|
@person.update_attributes({}).should be_true
|
136
136
|
end
|
137
137
|
|
@@ -140,7 +140,7 @@ describe Mongoid::Commands do
|
|
140
140
|
context "when validation fails" do
|
141
141
|
|
142
142
|
it "it raises an error" do
|
143
|
-
Mongoid::Commands::Save.expects(:execute).with(@person, true).returns(false)
|
143
|
+
Mongoid::Commands::Save.expects(:execute).with(@person, true, true).returns(false)
|
144
144
|
lambda { @person.update_attributes!({}) }.should raise_error
|
145
145
|
end
|
146
146
|
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Contexts::Enumerable do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@london = Address.new(:number => 1, :street => "Bond Street")
|
7
|
+
@shanghai = Address.new(:number => 10, :street => "Nan Jing Dong Lu")
|
8
|
+
@melbourne = Address.new(:number => 20, :street => "Bourke Street")
|
9
|
+
@new_york = Address.new(:number => 20, :street => "Broadway")
|
10
|
+
@docs = [ @london, @shanghai, @melbourne, @new_york ]
|
11
|
+
@selector = { :street => "Bond Street" }
|
12
|
+
@options = { :fields => [ :number ] }
|
13
|
+
@context = Mongoid::Contexts::Enumerable.new(@selector, @options, @docs)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#aggregate" do
|
17
|
+
|
18
|
+
before do
|
19
|
+
@counts = @context.aggregate
|
20
|
+
end
|
21
|
+
|
22
|
+
it "groups by the fields provided in the options" do
|
23
|
+
@counts.size.should == 3
|
24
|
+
end
|
25
|
+
|
26
|
+
it "stores the counts in proper groups" do
|
27
|
+
@counts[1].should == 1
|
28
|
+
@counts[10].should == 1
|
29
|
+
@counts[20].should == 2
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#count" do
|
34
|
+
|
35
|
+
it "returns the size of the enumerable" do
|
36
|
+
@context.count.should == 4
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#execute" do
|
42
|
+
|
43
|
+
it "returns the matching documents from the array" do
|
44
|
+
@context.execute.should == [ @london ]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#first" do
|
50
|
+
|
51
|
+
it "returns the first in the enumerable" do
|
52
|
+
@context.first.should == @london
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#group" do
|
58
|
+
|
59
|
+
before do
|
60
|
+
@group = @context.group
|
61
|
+
end
|
62
|
+
|
63
|
+
it "groups by the fields provided in the options" do
|
64
|
+
@group.size.should == 3
|
65
|
+
end
|
66
|
+
|
67
|
+
it "stores the documents in proper groups" do
|
68
|
+
@group[1].should == [ @london ]
|
69
|
+
@group[10].should == [ @shanghai ]
|
70
|
+
@group[20].should == [ @melbourne, @new_york ]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe ".initialize" do
|
76
|
+
|
77
|
+
let(:selector) { { :field => "value" } }
|
78
|
+
let(:options) { { :skip => 20 } }
|
79
|
+
let(:documents) { [stub] }
|
80
|
+
|
81
|
+
before do
|
82
|
+
@context = Mongoid::Contexts::Enumerable.new(selector, options, documents)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "sets the selector" do
|
86
|
+
@context.selector.should == selector
|
87
|
+
end
|
88
|
+
|
89
|
+
it "sets the options" do
|
90
|
+
@context.options.should == options
|
91
|
+
end
|
92
|
+
|
93
|
+
it "sets the documents" do
|
94
|
+
@context.documents.should == documents
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#last" do
|
100
|
+
|
101
|
+
it "returns the last in the enumerable" do
|
102
|
+
@context.last.should == @new_york
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#max" do
|
108
|
+
|
109
|
+
it "returns the max value for the supplied field" do
|
110
|
+
@context.max(:number).should == 20
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#min" do
|
116
|
+
|
117
|
+
it "returns the min value for the supplied field" do
|
118
|
+
@context.min(:number).should == 1
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#one" do
|
124
|
+
|
125
|
+
it "returns the first in the enumerable" do
|
126
|
+
@context.one.should == @london
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#page" do
|
132
|
+
|
133
|
+
context "when the page option exists" do
|
134
|
+
|
135
|
+
before do
|
136
|
+
@criteria = Mongoid::Criteria.new(Person).extras({ :page => 5 })
|
137
|
+
@context = Mongoid::Contexts::Enumerable.new({}, @criteria.options, [])
|
138
|
+
end
|
139
|
+
|
140
|
+
it "returns the page option" do
|
141
|
+
@context.page.should == 5
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when the page option does not exist" do
|
147
|
+
|
148
|
+
before do
|
149
|
+
@criteria = Mongoid::Criteria.new(Person)
|
150
|
+
@context = Mongoid::Contexts::Enumerable.new({}, @criteria.options, [])
|
151
|
+
end
|
152
|
+
|
153
|
+
it "returns 1" do
|
154
|
+
@context.page.should == 1
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#paginate" do
|
162
|
+
|
163
|
+
before do
|
164
|
+
@criteria = Person.where(:_id => "1").skip(60).limit(20)
|
165
|
+
@context = Mongoid::Contexts::Enumerable.new(@criteria.selector, @criteria.options, [])
|
166
|
+
@results = @context.paginate
|
167
|
+
end
|
168
|
+
|
169
|
+
it "executes and paginates the results" do
|
170
|
+
@results.current_page.should == 4
|
171
|
+
@results.per_page.should == 20
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "#per_page" do
|
177
|
+
|
178
|
+
context "when a limit option exists" do
|
179
|
+
|
180
|
+
it "returns 20" do
|
181
|
+
@context.per_page.should == 20
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
context "when a limit option does not exist" do
|
187
|
+
|
188
|
+
before do
|
189
|
+
@context = Mongoid::Contexts::Enumerable.new({}, { :limit => 50 }, [])
|
190
|
+
end
|
191
|
+
|
192
|
+
it "returns the limit" do
|
193
|
+
@context.per_page.should == 50
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#sum" do
|
201
|
+
|
202
|
+
it "returns the sum of all the field values" do
|
203
|
+
@context.sum(:number).should == 51
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
@@ -0,0 +1,370 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Contexts::Mongo do
|
4
|
+
|
5
|
+
describe "#aggregate" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@selector = {}
|
9
|
+
@options = { :fields => [:field1] }
|
10
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when klass not provided" do
|
14
|
+
|
15
|
+
before do
|
16
|
+
@reduce = "function(obj, prev) { prev.count++; }"
|
17
|
+
@collection = mock
|
18
|
+
Person.expects(:collection).returns(@collection)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "calls group on the collection with the aggregate js" do
|
22
|
+
@collection.expects(:group).with([:field1], {}, {:count => 0}, @reduce, true)
|
23
|
+
@context.aggregate
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#count" do
|
31
|
+
|
32
|
+
before do
|
33
|
+
@selector = { :_type => { "$in" => ["Doctor", "Person"] }, :test => "Testing" }
|
34
|
+
@options = {}
|
35
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when criteria has not been executed" do
|
39
|
+
|
40
|
+
before do
|
41
|
+
@context.instance_variable_set(:@count, 34)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns a count from the cursor" do
|
45
|
+
@context.count.should == 34
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when criteria has been executed" do
|
51
|
+
|
52
|
+
before do
|
53
|
+
@collection = mock
|
54
|
+
@cursor = mock
|
55
|
+
Person.expects(:collection).returns(@collection)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns the count from the cursor without creating the documents" do
|
59
|
+
@collection.expects(:find).with(@selector, {}).returns(@cursor)
|
60
|
+
@cursor.expects(:count).returns(10)
|
61
|
+
@context.count.should == 10
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#group" do
|
69
|
+
|
70
|
+
before do
|
71
|
+
@selector = { :_type => { "$in" => ["Doctor", "Person"] } }
|
72
|
+
@options = { :fields => [ :field1 ] }
|
73
|
+
@grouping = [{ "title" => "Sir", "group" => [{ "title" => "Sir", "age" => 30, "_type" => "Person" }] }]
|
74
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when klass provided" do
|
78
|
+
|
79
|
+
before do
|
80
|
+
@reduce = "function(obj, prev) { prev.group.push(obj); }"
|
81
|
+
@collection = mock
|
82
|
+
Person.expects(:collection).returns(@collection)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "calls group on the collection with the aggregate js" do
|
86
|
+
@collection.expects(:group).with([:field1], {:_type => { "$in" => ["Doctor", "Person"] }}, {:group => []}, @reduce, true).returns(@grouping)
|
87
|
+
@context.group
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#execute" do
|
95
|
+
|
96
|
+
let(:selector) { { :field => "value" } }
|
97
|
+
let(:options) { { :skip => 20 } }
|
98
|
+
|
99
|
+
before do
|
100
|
+
@cursor = stub(:count => 500)
|
101
|
+
@collection = mock
|
102
|
+
@person = mock
|
103
|
+
@klass = stub(:collection => @collection, :hereditary => false, :instantiate => @person)
|
104
|
+
@context = Mongoid::Contexts::Mongo.new(selector, options, @klass)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "calls find on the collection" do
|
108
|
+
@collection.expects(:find).with(selector, options).returns(@cursor)
|
109
|
+
@cursor.expects(:collect).yields({ :title => "Sir" }).returns([@person])
|
110
|
+
@context.execute.should == [@person]
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when field options are supplied" do
|
114
|
+
|
115
|
+
context "when _type not in the field list" do
|
116
|
+
|
117
|
+
before do
|
118
|
+
options[:fields] = [ :title ]
|
119
|
+
@expected_options = { :skip => 20, :fields => [ :title, :_type ] }
|
120
|
+
end
|
121
|
+
|
122
|
+
it "adds _type to the fields" do
|
123
|
+
@collection.expects(:find).with(selector, @expected_options).returns(@cursor)
|
124
|
+
@cursor.expects(:collect).yields({ :title => "Sir" }).returns([@person])
|
125
|
+
@context.execute.should == [@person]
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
describe ".initialize" do
|
135
|
+
|
136
|
+
let(:selector) { { :field => "value" } }
|
137
|
+
let(:options) { { :skip => 20 } }
|
138
|
+
let(:klass) { Person }
|
139
|
+
|
140
|
+
before do
|
141
|
+
@context = Mongoid::Contexts::Mongo.new(selector, options, klass)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "sets the selector" do
|
145
|
+
@context.selector.should == selector
|
146
|
+
end
|
147
|
+
|
148
|
+
it "sets the options" do
|
149
|
+
@context.options.should == options
|
150
|
+
end
|
151
|
+
|
152
|
+
it "sets the klass" do
|
153
|
+
@context.klass.should == klass
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "#last" do
|
159
|
+
|
160
|
+
before do
|
161
|
+
@collection = mock
|
162
|
+
Person.expects(:collection).returns(@collection)
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when documents exist" do
|
166
|
+
|
167
|
+
before do
|
168
|
+
@selector = {}
|
169
|
+
@options = { :sort => [[:title, :asc]] }
|
170
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
171
|
+
@collection.expects(:find_one).with(@selector, { :sort => [[:title, :desc]] }).returns(
|
172
|
+
{ "title" => "Sir", "_type" => "Person" }
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "calls find on the collection with the selector and sort options reversed" do
|
177
|
+
@context.last.should be_a_kind_of(Person)
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when no documents exist" do
|
183
|
+
|
184
|
+
before do
|
185
|
+
@selector = {}
|
186
|
+
@options = { :sort => [[:_id, :asc]] }
|
187
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
188
|
+
@collection.expects(:find_one).with(@selector, { :sort => [[:_id, :desc]] }).returns(nil)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "returns nil" do
|
192
|
+
@context.last.should be_nil
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
context "when no sorting options provided" do
|
198
|
+
|
199
|
+
before do
|
200
|
+
@selector = {}
|
201
|
+
@options = { :sort => [[:_id, :asc]] }
|
202
|
+
@context = Mongoid::Contexts::Mongo.new(@selector, @options, Person)
|
203
|
+
@collection.expects(:find_one).with(@selector, { :sort => [[:_id, :desc]] }).returns(
|
204
|
+
{ "title" => "Sir", "_type" => "Person" }
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "defaults to sort by id" do
|
209
|
+
@context.last
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "#max" do
|
217
|
+
|
218
|
+
before do
|
219
|
+
@reduce = Mongoid::Contexts::Mongo::MAX_REDUCE.gsub("[field]", "age")
|
220
|
+
@collection = mock
|
221
|
+
Person.expects(:collection).returns(@collection)
|
222
|
+
@context = Mongoid::Contexts::Mongo.new({}, {}, Person)
|
223
|
+
end
|
224
|
+
|
225
|
+
it "calls group on the collection with the aggregate js" do
|
226
|
+
@collection.expects(:group).with(
|
227
|
+
nil,
|
228
|
+
{},
|
229
|
+
{:max => "start"},
|
230
|
+
@reduce,
|
231
|
+
true
|
232
|
+
).returns([{"max" => 200.0}])
|
233
|
+
@context.max(:age).should == 200.0
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "#min" do
|
239
|
+
|
240
|
+
before do
|
241
|
+
@reduce = Mongoid::Contexts::Mongo::MIN_REDUCE.gsub("[field]", "age")
|
242
|
+
@collection = mock
|
243
|
+
Person.expects(:collection).returns(@collection)
|
244
|
+
@context = Mongoid::Contexts::Mongo.new({}, {}, Person)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "calls group on the collection with the aggregate js" do
|
248
|
+
@collection.expects(:group).with(
|
249
|
+
nil,
|
250
|
+
{},
|
251
|
+
{:min => "start"},
|
252
|
+
@reduce,
|
253
|
+
true
|
254
|
+
).returns([{"min" => 4.0}])
|
255
|
+
@context.min(:age).should == 4.0
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "#one" do
|
261
|
+
|
262
|
+
context "when documents exist" do
|
263
|
+
|
264
|
+
before do
|
265
|
+
@collection = mock
|
266
|
+
Person.expects(:collection).returns(@collection)
|
267
|
+
@context = Mongoid::Contexts::Mongo.new({}, {}, Person)
|
268
|
+
@collection.expects(:find_one).with({}, {}).returns(
|
269
|
+
{ "title"=> "Sir", "_type" => "Person" }
|
270
|
+
)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "calls find on the collection with the selector and options" do
|
274
|
+
@context.one.should be_a_kind_of(Person)
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
context "when no documents exist" do
|
280
|
+
|
281
|
+
before do
|
282
|
+
@collection = mock
|
283
|
+
Person.expects(:collection).returns(@collection)
|
284
|
+
@context = Mongoid::Contexts::Mongo.new({}, {}, Person)
|
285
|
+
@collection.expects(:find_one).with({}, {}).returns(nil)
|
286
|
+
end
|
287
|
+
|
288
|
+
it "returns nil" do
|
289
|
+
@context.one.should be_nil
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
describe "#page" do
|
297
|
+
|
298
|
+
context "when the page option exists" do
|
299
|
+
|
300
|
+
before do
|
301
|
+
@criteria = Mongoid::Criteria.new(Person).extras({ :page => 5 })
|
302
|
+
@context = Mongoid::Contexts::Mongo.new({}, @criteria.options, Person)
|
303
|
+
end
|
304
|
+
|
305
|
+
it "returns the page option" do
|
306
|
+
@context.page.should == 5
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
context "when the page option does not exist" do
|
312
|
+
|
313
|
+
before do
|
314
|
+
@criteria = Mongoid::Criteria.new(Person)
|
315
|
+
@context = Mongoid::Contexts::Mongo.new({}, @criteria.options, Person)
|
316
|
+
end
|
317
|
+
|
318
|
+
it "returns 1" do
|
319
|
+
@context.page.should == 1
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
describe "#paginate" do
|
327
|
+
|
328
|
+
before do
|
329
|
+
@collection = mock
|
330
|
+
Person.expects(:collection).returns(@collection)
|
331
|
+
@criteria = Person.where(:_id => "1").skip(60).limit(20)
|
332
|
+
@context = Mongoid::Contexts::Mongo.new(@criteria.selector, @criteria.options, Person)
|
333
|
+
@collection.expects(:find).with({:_type => { "$in" => ["Doctor", "Person"] }, :_id => "1"}, :skip => 60, :limit => 20).returns([])
|
334
|
+
@results = @context.paginate
|
335
|
+
end
|
336
|
+
|
337
|
+
it "executes and paginates the results" do
|
338
|
+
@results.current_page.should == 4
|
339
|
+
@results.per_page.should == 20
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "#sum" do
|
345
|
+
|
346
|
+
context "when klass not provided" do
|
347
|
+
|
348
|
+
before do
|
349
|
+
@reduce = Mongoid::Contexts::Mongo::SUM_REDUCE.gsub("[field]", "age")
|
350
|
+
@collection = mock
|
351
|
+
@context = Mongoid::Contexts::Mongo.new({}, {}, Person)
|
352
|
+
Person.expects(:collection).returns(@collection)
|
353
|
+
end
|
354
|
+
|
355
|
+
it "calls group on the collection with the aggregate js" do
|
356
|
+
@collection.expects(:group).with(
|
357
|
+
nil,
|
358
|
+
{},
|
359
|
+
{:sum => "start"},
|
360
|
+
@reduce,
|
361
|
+
true
|
362
|
+
).returns([{"sum" => 50.0}])
|
363
|
+
@context.sum(:age).should == 50.0
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
end
|