mongo_doc 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.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.textile +174 -0
- data/Rakefile +135 -0
- data/TODO +31 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +35 -0
- data/examples/simple_object.rb +30 -0
- data/features/finders.feature +76 -0
- data/features/mongodb.yml +7 -0
- data/features/mongodoc_base.feature +128 -0
- data/features/new_record.feature +36 -0
- data/features/partial_updates.feature +105 -0
- data/features/removing_documents.feature +68 -0
- data/features/saving_an_object.feature +15 -0
- data/features/scopes.feature +66 -0
- data/features/step_definitions/collection_steps.rb +14 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +30 -0
- data/features/step_definitions/finder_steps.rb +15 -0
- data/features/step_definitions/json_steps.rb +9 -0
- data/features/step_definitions/object_steps.rb +50 -0
- data/features/step_definitions/objects.rb +24 -0
- data/features/step_definitions/partial_update_steps.rb +32 -0
- data/features/step_definitions/query_steps.rb +54 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +128 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +105 -0
- data/lib/mongo_doc/associations/document_proxy.rb +56 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +98 -0
- data/lib/mongo_doc/associations/proxy_base.rb +53 -0
- data/lib/mongo_doc/attributes.rb +140 -0
- data/lib/mongo_doc/bson.rb +45 -0
- data/lib/mongo_doc/collection.rb +55 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts/enumerable.rb +128 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +232 -0
- data/lib/mongo_doc/contexts.rb +25 -0
- data/lib/mongo_doc/criteria.rb +38 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +216 -0
- data/lib/mongo_doc/ext/array.rb +5 -0
- data/lib/mongo_doc/ext/binary.rb +7 -0
- data/lib/mongo_doc/ext/boolean_class.rb +11 -0
- data/lib/mongo_doc/ext/date.rb +16 -0
- data/lib/mongo_doc/ext/date_time.rb +13 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -0
- data/lib/mongo_doc/ext/nil_class.rb +5 -0
- data/lib/mongo_doc/ext/numeric.rb +17 -0
- data/lib/mongo_doc/ext/object.rb +17 -0
- data/lib/mongo_doc/ext/object_id.rb +7 -0
- data/lib/mongo_doc/ext/regexp.rb +5 -0
- data/lib/mongo_doc/ext/string.rb +5 -0
- data/lib/mongo_doc/ext/symbol.rb +5 -0
- data/lib/mongo_doc/ext/time.rb +5 -0
- data/lib/mongo_doc/finders.rb +49 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/query.rb +7 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongo_doc.rb +19 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +247 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +92 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -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/mongo_doc.gemspec +205 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_runner.rb +90 -0
- data/perf/ruby_driver_runner.rb +64 -0
- data/script/console +8 -0
- data/spec/associations/collection_proxy_spec.rb +200 -0
- data/spec/associations/document_proxy_spec.rb +42 -0
- data/spec/associations/hash_proxy_spec.rb +163 -0
- data/spec/attributes_spec.rb +273 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +161 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/enumerable_spec.rb +274 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +198 -0
- data/spec/contexts_spec.rb +28 -0
- data/spec/criteria_spec.rb +33 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +664 -0
- data/spec/embedded_save_spec.rb +109 -0
- data/spec/finders_spec.rb +73 -0
- data/spec/hash_matchers.rb +27 -0
- data/spec/matchers_spec.rb +342 -0
- data/spec/mongodb.yml +6 -0
- data/spec/mongodb_pairs.yml +8 -0
- data/spec/new_record_spec.rb +128 -0
- data/spec/query_spec.rb +12 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +13 -0
- metadata +290 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe MongoDoc::Contexts::Enumerable do
|
|
4
|
+
|
|
5
|
+
class Address
|
|
6
|
+
include MongoDoc::Document
|
|
7
|
+
include MongoDoc::Matchers
|
|
8
|
+
|
|
9
|
+
key :number
|
|
10
|
+
key :street
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
@london = Address.new(:number => 1, :street => "Bond Street")
|
|
15
|
+
@shanghai = Address.new(:number => 10, :street => "Nan Jing Dong Lu")
|
|
16
|
+
@melbourne = Address.new(:number => 20, :street => "Bourke Street")
|
|
17
|
+
@new_york = Address.new(:number => 20, :street => "Broadway")
|
|
18
|
+
@docs = [ @london, @shanghai, @melbourne, @new_york ]
|
|
19
|
+
@criteria = Mongoid::Criteria.new(Address)
|
|
20
|
+
@criteria.documents = @docs
|
|
21
|
+
@criteria.where(:street => "Bourke Street").only(:number)
|
|
22
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "#aggregate" do
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
@counts = @context.aggregate
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "groups by the fields provided in the options" do
|
|
32
|
+
@counts.size.should == 3
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "stores the counts in proper groups" do
|
|
36
|
+
@counts[1].should == 1
|
|
37
|
+
@counts[10].should == 1
|
|
38
|
+
@counts[20].should == 2
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "#count" do
|
|
43
|
+
|
|
44
|
+
it "returns the size of the enumerable" do
|
|
45
|
+
@context.count.should == 4
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#execute" do
|
|
51
|
+
|
|
52
|
+
before do
|
|
53
|
+
@criteria = Mongoid::Criteria.new(Address)
|
|
54
|
+
@criteria.documents = @docs
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "returns the matching documents from the array" do
|
|
58
|
+
@context.execute.should == [ @melbourne ]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when selector is empty" do
|
|
62
|
+
|
|
63
|
+
before do
|
|
64
|
+
@criteria.only(:number)
|
|
65
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "returns all the documents" do
|
|
69
|
+
@context.execute.should == @docs
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "when skip and limit are in the options" do
|
|
74
|
+
|
|
75
|
+
before do
|
|
76
|
+
@criteria.skip(2).limit(2)
|
|
77
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "properly narrows down the matching results" do
|
|
81
|
+
@context.execute.should == [ @melbourne, @new_york ]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "#first" do
|
|
88
|
+
|
|
89
|
+
context "when a selector is present" do
|
|
90
|
+
|
|
91
|
+
it "returns the first that matches the selector" do
|
|
92
|
+
@context.first.should == @melbourne
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe "#group" do
|
|
99
|
+
|
|
100
|
+
before do
|
|
101
|
+
@group = @context.group
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "groups by the fields provided in the options" do
|
|
105
|
+
@group.size.should == 3
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "stores the documents in proper groups" do
|
|
109
|
+
@group[1].should == [ @london ]
|
|
110
|
+
@group[10].should == [ @shanghai ]
|
|
111
|
+
@group[20].should == [ @melbourne, @new_york ]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "#initialize" do
|
|
117
|
+
|
|
118
|
+
let(:selector) { { :field => "value" } }
|
|
119
|
+
let(:options) { { :skip => 20 } }
|
|
120
|
+
let(:documents) { [stub] }
|
|
121
|
+
|
|
122
|
+
before do
|
|
123
|
+
@criteria = Mongoid::Criteria.new(Address)
|
|
124
|
+
@criteria.documents = documents
|
|
125
|
+
@criteria.where(selector).skip(20)
|
|
126
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "sets the selector" do
|
|
130
|
+
@context.selector.should == selector
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "sets the options" do
|
|
134
|
+
@context.options.should == options
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "sets the documents" do
|
|
138
|
+
@context.documents.should == documents
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe "#iterator" do
|
|
144
|
+
|
|
145
|
+
before do
|
|
146
|
+
@criteria.where(:street => "Bourke Street")
|
|
147
|
+
@criteria.documents = @docs
|
|
148
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "executes the criteria" do
|
|
152
|
+
acc = []
|
|
153
|
+
@context.iterate do |doc|
|
|
154
|
+
acc << doc
|
|
155
|
+
end
|
|
156
|
+
acc.should == [@melbourne]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
describe "#last" do
|
|
162
|
+
|
|
163
|
+
it "returns the last matching in the enumerable" do
|
|
164
|
+
@context.last.should == @melbourne
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe "#max" do
|
|
170
|
+
|
|
171
|
+
it "returns the max value for the supplied field" do
|
|
172
|
+
@context.max(:number).should == 20
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe "#min" do
|
|
178
|
+
|
|
179
|
+
it "returns the min value for the supplied field" do
|
|
180
|
+
@context.min(:number).should == 1
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe "#one" do
|
|
186
|
+
|
|
187
|
+
it "returns the first matching in the enumerable" do
|
|
188
|
+
@context.one.should == @melbourne
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe "#page" do
|
|
194
|
+
|
|
195
|
+
context "when the page option exists" do
|
|
196
|
+
|
|
197
|
+
before do
|
|
198
|
+
@criteria = Mongoid::Criteria.new(Address).extras({ :page => 5 })
|
|
199
|
+
@criteria.documents = []
|
|
200
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "returns the page option" do
|
|
204
|
+
@context.page.should == 5
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context "when the page option does not exist" do
|
|
210
|
+
|
|
211
|
+
before do
|
|
212
|
+
@criteria = Mongoid::Criteria.new(Address)
|
|
213
|
+
@criteria.documents = []
|
|
214
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "returns 1" do
|
|
218
|
+
@context.page.should == 1
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
describe "#paginate" do
|
|
226
|
+
|
|
227
|
+
before do
|
|
228
|
+
@criteria = Mongoid::Criteria.new(Address).skip(2).limit(2)
|
|
229
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
230
|
+
@results = @context.paginate
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "executes and paginates the results" do
|
|
234
|
+
@results.current_page.should == 2
|
|
235
|
+
@results.per_page.should == 2
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
describe "#per_page" do
|
|
241
|
+
|
|
242
|
+
context "when a limit option exists" do
|
|
243
|
+
|
|
244
|
+
it "returns 20" do
|
|
245
|
+
@context.per_page.should == 20
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context "when a limit option does not exist" do
|
|
251
|
+
|
|
252
|
+
before do
|
|
253
|
+
@criteria = Mongoid::Criteria.new(Address).limit(50)
|
|
254
|
+
@criteria.documents = []
|
|
255
|
+
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "returns the limit" do
|
|
259
|
+
@context.per_page.should == 50
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe "#sum" do
|
|
267
|
+
|
|
268
|
+
it "returns the sum of all the field values" do
|
|
269
|
+
@context.sum(:number).should == 51
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Contexts::Ids" do
|
|
4
|
+
|
|
5
|
+
class Address
|
|
6
|
+
include MongoDoc::Document
|
|
7
|
+
include MongoDoc::Matchers
|
|
8
|
+
|
|
9
|
+
key :number
|
|
10
|
+
key :street
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:criteria) { Mongoid::Criteria.new(Address) }
|
|
14
|
+
let(:context) { criteria.context }
|
|
15
|
+
|
|
16
|
+
context "#id_criteria" do
|
|
17
|
+
context "single id" do
|
|
18
|
+
let(:id) { 'a' * 24 }
|
|
19
|
+
let(:obj_id) { Mongo::ObjectID.from_string(id) }
|
|
20
|
+
|
|
21
|
+
it "converts strings to an object id" do
|
|
22
|
+
criteria.should_receive(:id).with(obj_id)
|
|
23
|
+
context.stub(:one)
|
|
24
|
+
context.id_criteria(id)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "delegates to one if passed a string or ObjectID" do
|
|
28
|
+
context.should_receive(:one)
|
|
29
|
+
context.id_criteria(id)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "mutliple ids" do
|
|
34
|
+
let(:ids) { ['a' * 24, 'b' * 24] }
|
|
35
|
+
let(:obj_ids) { [Mongo::ObjectID.from_string(ids.first), Mongo::ObjectID.from_string(ids.last)] }
|
|
36
|
+
|
|
37
|
+
it "converts strings to an object id" do
|
|
38
|
+
criteria.should_receive(:id).with(obj_ids)
|
|
39
|
+
criteria.stub(:entries)
|
|
40
|
+
context.id_criteria(ids)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "delegates to entries if passed an array" do
|
|
44
|
+
criteria.should_receive(:entries)
|
|
45
|
+
context.id_criteria(ids)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Contexts::MongoDoc" do
|
|
4
|
+
|
|
5
|
+
class Address
|
|
6
|
+
include MongoDoc::Document
|
|
7
|
+
include MongoDoc::Matchers
|
|
8
|
+
|
|
9
|
+
key :number
|
|
10
|
+
key :street
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:criteria) { Mongoid::Criteria.new(Address) }
|
|
14
|
+
let(:context) { criteria.context }
|
|
15
|
+
|
|
16
|
+
context "#initialize" do
|
|
17
|
+
it "sets the criteria" do
|
|
18
|
+
context.criteria.should == criteria
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "#collection" do
|
|
23
|
+
it "delegates to klass" do
|
|
24
|
+
klass = mock('klass', :collection => true)
|
|
25
|
+
context.should_receive(:klass).and_return(klass)
|
|
26
|
+
context.collection
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "querying" do
|
|
31
|
+
let(:collection) { stub('collection') }
|
|
32
|
+
|
|
33
|
+
before { context.stub(:collection).and_return(collection) }
|
|
34
|
+
|
|
35
|
+
context "#aggregate" do
|
|
36
|
+
it "uses group with the appropriate JS" do
|
|
37
|
+
collection.should_receive(:group).with(nil, {}, {:count=>0}, MongoDoc::Contexts::Mongo::AGGREGATE_REDUCE, true)
|
|
38
|
+
context.aggregate
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "#count" do
|
|
43
|
+
it "uses find and count" do
|
|
44
|
+
result = stub('result')
|
|
45
|
+
result.should_receive(:count)
|
|
46
|
+
collection.should_receive(:find).and_return(result)
|
|
47
|
+
context.count
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "#execute" do
|
|
52
|
+
it "uses find" do
|
|
53
|
+
collection.should_receive(:find)
|
|
54
|
+
context.execute
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "returns [] if nothing returned from find" do
|
|
58
|
+
collection.stub(:find => nil)
|
|
59
|
+
context.execute.should == []
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "returns the cursor if one is returned from find" do
|
|
63
|
+
cursor = stub('cursor')
|
|
64
|
+
collection.stub(:find => cursor)
|
|
65
|
+
context.execute.should == cursor
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "memoizes the count if paginating" do
|
|
69
|
+
count = 20
|
|
70
|
+
cursor = stub('cursor', :count => count)
|
|
71
|
+
collection.stub(:find => cursor)
|
|
72
|
+
context.execute
|
|
73
|
+
context.count.should == count
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "#group" do
|
|
78
|
+
it "uses group with the appropriate JS" do
|
|
79
|
+
collection.should_receive(:group).with(nil, {}, {:group=>[]}, MongoDoc::Contexts::Mongo::GROUP_REDUCE, true).and_return([])
|
|
80
|
+
context.group
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "decodes returned documents" do
|
|
84
|
+
doc = stub('doc')
|
|
85
|
+
collection.stub(:group).and_return([{:group => [doc]}])
|
|
86
|
+
MongoDoc::BSON.should_receive(:decode).and_return(doc)
|
|
87
|
+
context.group
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context "#iterate" do
|
|
92
|
+
|
|
93
|
+
it "delegates to caching if cached" do
|
|
94
|
+
context.should_receive(:caching)
|
|
95
|
+
criteria.cache
|
|
96
|
+
context.iterate
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "iterates over the results of execute" do
|
|
100
|
+
item = stub('item')
|
|
101
|
+
context.stub(:execute).and_return([item])
|
|
102
|
+
context.iterate do |doc|
|
|
103
|
+
doc.should == item
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "#caching" do
|
|
108
|
+
let(:item) { stub('item') }
|
|
109
|
+
|
|
110
|
+
before do
|
|
111
|
+
criteria.cache
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context "when not previously cached" do
|
|
115
|
+
it "iterates over the results of execute" do
|
|
116
|
+
context.stub(:execute).and_return([item])
|
|
117
|
+
context.iterate do |doc|
|
|
118
|
+
doc.should == item
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "memoizes the result" do
|
|
123
|
+
context.stub(:execute).and_return([item])
|
|
124
|
+
context.iterate
|
|
125
|
+
context.cache.should == [item]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context "when previously cached" do
|
|
130
|
+
before do
|
|
131
|
+
context.instance_variable_set(:@cache, [item])
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "does not execute" do
|
|
135
|
+
context.should_not_receive(:execute)
|
|
136
|
+
context.iterate do |doc|
|
|
137
|
+
doc.should == item
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "iterates over the results of execute" do
|
|
142
|
+
context.should_not_receive(:execute)
|
|
143
|
+
acc = []
|
|
144
|
+
context.iterate do |doc|
|
|
145
|
+
acc << doc
|
|
146
|
+
end
|
|
147
|
+
acc.should == [item]
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
context "#last" do
|
|
154
|
+
it "delegates to find_one" do
|
|
155
|
+
collection.should_receive(:find_one).with({}, {:sort=>[[:_id, :desc]]})
|
|
156
|
+
context.last
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
context "#max" do
|
|
161
|
+
it "delegates to grouped" do
|
|
162
|
+
context.should_receive(:grouped).with(:max, "number", MongoDoc::Contexts::Mongo::MAX_REDUCE)
|
|
163
|
+
context.max(:number)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
context "#min" do
|
|
168
|
+
it "delegates to grouped" do
|
|
169
|
+
context.should_receive(:grouped).with(:min, "number", MongoDoc::Contexts::Mongo::MIN_REDUCE)
|
|
170
|
+
context.min(:number)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
context "#one" do
|
|
175
|
+
it "delegates to find_one" do
|
|
176
|
+
collection.should_receive(:find_one).with({}, {})
|
|
177
|
+
context.one
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
context "#sum" do
|
|
182
|
+
it "delegates to grouped" do
|
|
183
|
+
context.should_receive(:grouped).with(:sum, "number", MongoDoc::Contexts::Mongo::SUM_REDUCE)
|
|
184
|
+
context.sum(:number)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
context "#grouped" do
|
|
189
|
+
it "delegates to group" do
|
|
190
|
+
op = 'op'
|
|
191
|
+
field = 'name'
|
|
192
|
+
reduce = '[field]'
|
|
193
|
+
collection.should_receive(:group).with(nil, {}, {op =>"start"}, field, true).and_return([])
|
|
194
|
+
context.send(:grouped, op, field, reduce)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe MongoDoc::Contexts do
|
|
4
|
+
|
|
5
|
+
context ".context_for" do
|
|
6
|
+
let(:criteria) { stub('criteria', :klass => klass) }
|
|
7
|
+
|
|
8
|
+
context "when criteria is for a top-level MongoDoc::Document" do
|
|
9
|
+
let(:klass) { stub('klass', :collection => stub('collection')) }
|
|
10
|
+
|
|
11
|
+
it "creates a MongoDoc context" do
|
|
12
|
+
MongoDoc::Contexts::Mongo.should_receive(:new).with(criteria)
|
|
13
|
+
Mongoid::Contexts.context_for(criteria)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "when criteria is for an embedded MongoDoc::Document" do
|
|
18
|
+
let(:klass) { stub('klass') }
|
|
19
|
+
|
|
20
|
+
it "creates an Enumerable context" do
|
|
21
|
+
MongoDoc::Contexts::Enumerable.should_receive(:new).with(criteria)
|
|
22
|
+
Mongoid::Contexts.context_for(criteria)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe MongoDoc::Criteria do
|
|
4
|
+
|
|
5
|
+
class CriteriaTest
|
|
6
|
+
extend MongoDoc::Criteria
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context ".criteria" do
|
|
10
|
+
it "creates a new criteria for the document" do
|
|
11
|
+
CriteriaTest.criteria.should be_a_kind_of(Mongoid::Criteria)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "sets the criteria klass" do
|
|
15
|
+
CriteriaTest.criteria.klass.should == CriteriaTest
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context "criteria delegates" do
|
|
20
|
+
let(:criteria) { stub('criteria').as_null_object }
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
CriteriaTest.stub(:criteria).and_return(criteria)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
%w(and cache enslave excludes extras id in limit not_in offset only order_by page per_page skip where).each do |criteria_op|
|
|
27
|
+
it "#{criteria_op} delegates to the criteria" do
|
|
28
|
+
criteria.should_receive(criteria_op)
|
|
29
|
+
CriteriaTest.send(criteria_op)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/spec/cursor_spec.rb
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Cursor" do
|
|
4
|
+
let(:mongo_cursor) { stub('cursor') }
|
|
5
|
+
|
|
6
|
+
let(:collection) { stub('collection') }
|
|
7
|
+
|
|
8
|
+
let(:cursor) { MongoDoc::Cursor.new(collection, mongo_cursor) }
|
|
9
|
+
|
|
10
|
+
it "is Enumerable" do
|
|
11
|
+
Enumerable.should === cursor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it ".new wraps a Mongo::Cursor" do
|
|
15
|
+
cursor._cursor.should == mongo_cursor
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "#collection returns the MongoDoc::Collection for this cursor" do
|
|
19
|
+
cursor.collection.should == collection
|
|
20
|
+
cursor._collection.should == collection
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "with the underlying cursor" do
|
|
24
|
+
%w(admin close closed? count explain fields full_collection_name hint limit order query_options_hash query_opts selector skip snapshot sort timeout).each do |delegated_method|
|
|
25
|
+
it "delegates #{delegated_method} to the Mongo::Cursor" do
|
|
26
|
+
mongo_cursor.should_receive(delegated_method)
|
|
27
|
+
cursor.send(delegated_method)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "#each" do
|
|
33
|
+
it "delegates to the cursor" do
|
|
34
|
+
mongo_cursor.should_receive(:each)
|
|
35
|
+
cursor.each
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "decodes the return from the delegate" do
|
|
39
|
+
bson = stub('bson')
|
|
40
|
+
cursor.stub(:_cursor).and_return([bson])
|
|
41
|
+
MongoDoc::BSON.should_receive(:decode).with(bson)
|
|
42
|
+
cursor.each {}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "calls the block with the decoded return" do
|
|
46
|
+
result = stub('bson')
|
|
47
|
+
cursor.stub(:_cursor).and_return([result])
|
|
48
|
+
MongoDoc::BSON.stub(:decode).and_return(result)
|
|
49
|
+
cursor.each {|obj| @obj = obj}
|
|
50
|
+
@obj.should == result
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "#next_document" do
|
|
55
|
+
it "delegates to the cursor" do
|
|
56
|
+
mongo_cursor.should_receive(:next_document)
|
|
57
|
+
cursor.next_document
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "decodes the return from the delegate" do
|
|
61
|
+
bson = stub('bson')
|
|
62
|
+
mongo_cursor.stub(:next_document).and_return(bson)
|
|
63
|
+
MongoDoc::BSON.should_receive(:decode).with(bson)
|
|
64
|
+
cursor.next_document
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "returns nil if the delegate returns nil" do
|
|
68
|
+
mongo_cursor.stub(:next_document)
|
|
69
|
+
cursor.next_document.should be_nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "#to_a" do
|
|
74
|
+
it "delegates to the cursor" do
|
|
75
|
+
mongo_cursor.should_receive(:to_a)
|
|
76
|
+
cursor.to_a
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "decodes the return from the delegate" do
|
|
80
|
+
array = stub('array')
|
|
81
|
+
mongo_cursor.stub(:to_a).and_return(array)
|
|
82
|
+
MongoDoc::BSON.should_receive(:decode).with(array)
|
|
83
|
+
cursor.to_a
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "returns [] if the delegate returns []" do
|
|
87
|
+
mongo_cursor.stub(:to_a).and_return([])
|
|
88
|
+
cursor.to_a.should == []
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|