mongodoc 0.2.2 → 0.2.4

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.
Files changed (57) hide show
  1. data/Rakefile +21 -0
  2. data/TODO +6 -1
  3. data/VERSION +1 -1
  4. data/features/finders.feature +1 -1
  5. data/features/mongodoc_base.feature +11 -2
  6. data/features/{named_scopes.feature → scopes.feature} +0 -0
  7. data/features/step_definitions/document_steps.rb +15 -4
  8. data/features/step_definitions/documents.rb +3 -3
  9. data/features/step_definitions/query_steps.rb +17 -14
  10. data/features/step_definitions/{named_scope_steps.rb → scope_steps.rb} +0 -0
  11. data/features/using_criteria.feature +22 -43
  12. data/lib/mongodoc.rb +1 -1
  13. data/lib/mongodoc/associations/collection_proxy.rb +3 -1
  14. data/lib/mongodoc/associations/document_proxy.rb +4 -1
  15. data/lib/mongodoc/associations/hash_proxy.rb +3 -1
  16. data/lib/mongodoc/associations/proxy_base.rb +6 -4
  17. data/lib/mongodoc/attributes.rb +6 -6
  18. data/lib/mongodoc/contexts.rb +24 -0
  19. data/lib/mongodoc/contexts/enumerable.rb +132 -0
  20. data/lib/mongodoc/contexts/mongo.rb +215 -0
  21. data/lib/mongodoc/criteria.rb +36 -479
  22. data/lib/mongodoc/document.rb +3 -2
  23. data/lib/mongodoc/finders.rb +31 -11
  24. data/lib/mongodoc/matchers.rb +35 -0
  25. data/lib/mongodoc/scope.rb +64 -0
  26. data/lib/mongoid/contexts/paging.rb +42 -0
  27. data/lib/mongoid/criteria.rb +264 -0
  28. data/lib/mongoid/criterion/complex.rb +21 -0
  29. data/lib/mongoid/criterion/exclusion.rb +65 -0
  30. data/lib/mongoid/criterion/inclusion.rb +92 -0
  31. data/lib/mongoid/criterion/optional.rb +136 -0
  32. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  33. data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
  34. data/lib/mongoid/matchers/all.rb +11 -0
  35. data/lib/mongoid/matchers/default.rb +26 -0
  36. data/lib/mongoid/matchers/exists.rb +13 -0
  37. data/lib/mongoid/matchers/gt.rb +11 -0
  38. data/lib/mongoid/matchers/gte.rb +11 -0
  39. data/lib/mongoid/matchers/in.rb +11 -0
  40. data/lib/mongoid/matchers/lt.rb +11 -0
  41. data/lib/mongoid/matchers/lte.rb +11 -0
  42. data/lib/mongoid/matchers/ne.rb +11 -0
  43. data/lib/mongoid/matchers/nin.rb +11 -0
  44. data/lib/mongoid/matchers/size.rb +11 -0
  45. data/mongodoc.gemspec +39 -9
  46. data/spec/attributes_spec.rb +16 -2
  47. data/spec/contexts/enumerable_spec.rb +335 -0
  48. data/spec/contexts/mongo_spec.rb +148 -0
  49. data/spec/contexts_spec.rb +28 -0
  50. data/spec/criteria_spec.rb +15 -766
  51. data/spec/finders_spec.rb +28 -36
  52. data/spec/matchers_spec.rb +342 -0
  53. data/spec/scope_spec.rb +79 -0
  54. metadata +40 -10
  55. data/features/step_definitions/criteria_steps.rb +0 -42
  56. data/lib/mongodoc/named_scope.rb +0 -68
  57. data/spec/named_scope_spec.rb +0 -82
@@ -0,0 +1,148 @@
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 "#id_criteria" do
92
+ it "delegates to one if passed a string or ObjectID" do
93
+ context.should_receive(:one)
94
+ context.id_criteria('id')
95
+ end
96
+
97
+ it "delegates to entries if passed an array" do
98
+ criteria.should_receive(:entries)
99
+ context.id_criteria(['id'])
100
+ end
101
+ end
102
+
103
+ context "#last" do
104
+ it "delegates to find_one" do
105
+ collection.should_receive(:find_one).with({}, {:sort=>[[:_id, :desc]]})
106
+ context.last
107
+ end
108
+ end
109
+
110
+ context "#max" do
111
+ it "delegates to grouped" do
112
+ context.should_receive(:grouped).with(:max, "number", MongoDoc::Contexts::Mongo::MAX_REDUCE)
113
+ context.max(:number)
114
+ end
115
+ end
116
+
117
+ context "#min" do
118
+ it "delegates to grouped" do
119
+ context.should_receive(:grouped).with(:min, "number", MongoDoc::Contexts::Mongo::MIN_REDUCE)
120
+ context.min(:number)
121
+ end
122
+ end
123
+
124
+ context "#one" do
125
+ it "delegates to find_one" do
126
+ collection.should_receive(:find_one).with({}, {})
127
+ context.one
128
+ end
129
+ end
130
+
131
+ context "#sum" do
132
+ it "delegates to grouped" do
133
+ context.should_receive(:grouped).with(:sum, "number", MongoDoc::Contexts::Mongo::SUM_REDUCE)
134
+ context.sum(:number)
135
+ end
136
+ end
137
+
138
+ context "#grouped" do
139
+ it "delegates to group" do
140
+ op = 'op'
141
+ field = 'name'
142
+ reduce = '[field]'
143
+ collection.should_receive(:group).with(nil, {}, {op =>"start"}, field, true).and_return([])
144
+ context.send(:grouped, op, field, reduce)
145
+ end
146
+ end
147
+ end
148
+ 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
+
@@ -1,784 +1,33 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper.rb"))
1
+ require 'spec_helper'
2
2
 
3
3
  describe MongoDoc::Criteria do
4
- class CountryCode
5
- include MongoDoc::Document
6
4
 
7
- key :code
5
+ class CriteriaTest
6
+ extend MongoDoc::Criteria
8
7
  end
9
8
 
10
- class Phone
11
- include MongoDoc::Document
12
-
13
- key :number
14
- has_one :country_code
15
- end
16
-
17
- class Animal
18
- include MongoDoc::Document
19
-
20
- key :name
21
- end
22
-
23
- class Address
24
- include MongoDoc::Document
25
-
26
- key :street
27
- key :city
28
- key :state
29
- key :post_code
30
- end
31
-
32
- class Name
33
- include MongoDoc::Document
34
-
35
- key :first_name
36
- key :last_name
37
- end
38
-
39
- class Person
40
- include MongoDoc::Document
41
-
42
- key :title
43
- key :terms
44
- key :age
45
- key :dob
46
- key :mixed_drink
47
- key :employer_id
48
- key :lunch_time
49
-
50
- has_many :addresses
51
- has_many :phone_numbers, :class_name => "Phone"
52
-
53
- has_one :name
54
- has_one :pet
55
-
56
- def update_addresses
57
- addresses.each_with_index do |address, i|
58
- address.street = "Updated #{i}"
59
- end
60
- end
61
-
62
- def employer=(emp)
63
- self.employer_id = emp.id
64
- end
65
- end
66
-
67
- before do
68
- @criteria = MongoDoc::Criteria.new(Person)
69
- end
70
-
71
- describe "#all" do
72
- it "calls collect" do
73
- @criteria.should_receive(:collect).with(no_args)
74
- @criteria.all
75
- end
76
- end
77
-
78
- describe "#aggregate" do
79
- before do
80
- @reduce = "function(obj, prev) { prev.count++; }"
81
- @collection = mock
82
- Person.should_receive(:collection).and_return(@collection)
83
- end
84
-
85
- it "calls group on the collection with the aggregate js" do
86
- @collection.should_receive(:group).with([:field1], {}, {:count => 0}, @reduce, true)
87
- @criteria.only(:field1).aggregate
88
- end
89
- end
90
-
91
- describe "#every" do
92
-
93
- it "adds the $all query to the selector" do
94
- @criteria.every(:title => ["title1", "title2"])
95
- @criteria.selector.should == { :title => { "$all" => ["title1", "title2"] } }
96
- end
97
-
98
- it "returns self" do
99
- @criteria.every(:title => [ "title1" ]).should == @criteria
100
- end
101
-
102
- end
103
-
104
- describe "including Enumerable" do
105
-
106
- before do
107
- @cursor = stub('cursor').as_null_object
108
- @criteria.stub(:execute).and_return(@cursor)
109
- end
110
-
111
- it "calls each" do
112
- @criteria.should_receive(:each).and_return(@criteria)
113
- @criteria.collect
114
- end
115
-
116
- end
117
-
118
- describe "#count" do
119
-
120
- context "when criteria has not been executed" do
121
-
122
- before do
123
- @count = 27
124
- @collection = mock
125
- @cursor = stub('cursor', :count => @count)
126
- Person.stub(:collection).and_return(@collection)
127
- end
128
-
129
- it "calls through to the collection" do
130
- @collection.should_receive(:find).and_return(@cursor)
131
- @criteria.count
132
- end
133
-
134
- it "returns the count from the cursor" do
135
- @collection.stub(:find).and_return(@cursor)
136
- @criteria.count.should == @count
137
- end
138
-
139
- end
140
-
141
- context "when criteria has been executed" do
142
-
143
- before do
144
- @count = 28
145
- @criteria.instance_variable_set(:@count, @count)
146
- end
147
-
148
- it "returns the count from the cursor without creating the documents" do
149
- @criteria.count.should == @count
150
- end
151
-
152
- end
153
-
154
- end
155
-
156
- describe "#each" do
157
-
158
- before do
159
- @criteria.where(:title => "Sir")
160
- @person = Person.new(:title => "Sir")
161
- @cursor = [@person]
162
- end
163
-
164
- context "when no block given" do
165
- it "executes the criteria" do
166
- @criteria.should_receive(:execute).and_return(@cursor)
167
- @criteria.each
168
- end
169
-
170
- it "has memoized the result of execute" do
171
- @criteria.stub(:execute).and_return(@cursor)
172
- @criteria.each
173
- @criteria.collection.should == @cursor
174
- end
175
-
176
- it "returns self" do
177
- @criteria.stub(:execute).and_return(@cursor)
178
- @criteria.each.should == @criteria
179
- end
180
- end
181
-
182
- context "when a block is given" do
183
- class CursorStub
184
- include Enumerable
185
-
186
- attr_accessor :data
187
-
188
- def each(*args, &block)
189
- data.each(*args, &block)
190
- end
191
- end
192
-
193
- context "when the criteria has not been executed" do
194
- before do
195
- @cursor = CursorStub.new
196
- @cursor.data = [@person]
197
- end
198
-
199
- it "executes the criteria" do
200
- @criteria.should_receive(:execute).and_return(@cursor)
201
- @criteria.each do |person|
202
- person.should == @person
203
- end
204
- end
205
-
206
- it "yields into the block" do
207
- @criteria.stub(:execute).and_return(@cursor)
208
- @criteria.each do |person|
209
- @result = person
210
- end
211
- @result.should == @person
212
- end
213
-
214
- it "has memoized the cursor iteration" do
215
- @criteria.stub(:execute).and_return(@cursor)
216
- @criteria.each do |person|
217
- @result = person
218
- end
219
- @criteria.collection.should == [@person]
220
- end
221
-
222
-
223
- it "returns self" do
224
- @criteria.stub(:execute).and_return(@cursor)
225
- @criteria.each.should == @criteria
226
- end
227
- end
228
-
229
- context "when the criteria has been executed" do
230
- before do
231
- @criteria.stub(:execute).and_return(@cursor)
232
- @criteria.each
233
- end
234
-
235
- it "does not execute the criteria" do
236
- @criteria.should_not_receive(:execute)
237
- @criteria.each do |person|
238
- person.should == @person
239
- end
240
- end
241
-
242
- it "yields into the block" do
243
- @criteria.each do |person|
244
- @result = person
245
- end
246
- @result.should == @person
247
- end
248
-
249
- it "returns self" do
250
- @criteria.each.should == @criteria
251
- end
252
- end
253
- end
254
- end
255
-
256
- describe "#excludes" do
257
-
258
- it "adds the $ne query to the selector" do
259
- @criteria.excludes(:title => "Bad Title", :text => "Bad Text")
260
- @criteria.selector.should == { :title => { "$ne" => "Bad Title"}, :text => { "$ne" => "Bad Text" } }
261
- end
262
-
263
- it "returns self" do
264
- @criteria.excludes(:title => "Bad").should == @criteria
265
- end
266
-
267
- end
268
-
269
- describe "#extras" do
270
-
271
- context "filtering" do
272
-
273
- context "when page is provided" do
274
-
275
- it "sets the limit and skip options" do
276
- @criteria.extras({ :page => "2" })
277
- @criteria.page.should == 2
278
- @criteria.options.should == { :skip => 20, :limit => 20 }
279
- end
280
-
281
- end
282
-
283
- context "when per_page is provided" do
284
-
285
- it "sets the limit and skip options" do
286
- @criteria.extras({ :per_page => 45 })
287
- @criteria.options.should == { :skip => 0, :limit => 45 }
288
- end
289
-
290
- end
291
-
292
- context "when page and per_page both provided" do
293
-
294
- it "sets the limit and skip options" do
295
- @criteria.extras({ :per_page => 30, :page => "4" })
296
- @criteria.options.should == { :skip => 90, :limit => 30 }
297
- @criteria.page.should == 4
298
- end
299
-
300
- end
301
-
302
- end
303
-
304
- it "adds the extras to the options" do
305
- @criteria.extras({ :skip => 10 })
306
- @criteria.options.should == { :skip => 10 }
307
- end
308
-
309
- it "returns self" do
310
- @criteria.extras({}).should == @criteria
311
- end
312
-
313
- it "adds the extras without overwriting existing options" do
314
- @criteria.order_by([:field1])
315
- @criteria.extras({ :skip => 10 })
316
- @criteria.options.should have_key(:sort)
317
- end
318
-
319
- end
320
-
321
- describe "#group" do
322
- before do
323
- @grouping = [{ "title" => "Sir", "group" => [{ "title" => "Sir", "age" => 30 }] }]
324
- @reduce = "function(obj, prev) { prev.group.push(obj); }"
325
- @collection = mock
326
- Person.should_receive(:collection).and_return(@collection)
327
- end
328
-
329
- it "calls group on the collection with the aggregate js" do
330
- @collection.should_receive(:group).with([:field1], {}, {:group => []}, @reduce, true).and_return(@grouping)
331
- @criteria.only(:field1).group
332
- end
333
- end
334
-
335
- describe "#id" do
336
-
337
- it "adds the ObjectID as the _id query to the selector" do
338
- id = Mongo::ObjectID.new
339
- @criteria.id(id)
340
- @criteria.selector.should == { :_id => id }
341
- end
342
-
343
- it "when a string adds ObjectID as the _id query to the selector" do
344
- id = Mongo::ObjectID.new
345
- @criteria.id(id.to_s)
346
- @criteria.selector.should == { :_id => id }
347
- end
348
-
349
- it "returns self" do
350
- id = Mongo::ObjectID.new
351
- @criteria.id(id).should == @criteria
352
- end
353
-
354
- end
355
-
356
- describe "#in" do
357
-
358
- it "adds the $in clause to the selector" do
359
- @criteria.in(:title => ["title1", "title2"], :text => ["test"])
360
- @criteria.selector.should == { :title => { "$in" => ["title1", "title2"] }, :text => { "$in" => ["test"] } }
361
- end
362
-
363
- it "returns self" do
364
- @criteria.in(:title => ["title1"]).should == @criteria
365
- end
366
-
367
- end
368
-
369
- describe "#last" do
370
-
371
- context "when documents exist" do
372
-
373
- before do
374
- @collection = mock
375
- Person.should_receive(:collection).and_return(@collection)
376
- @collection.should_receive(:find_one).with(@criteria.selector, { :sort => [[:title, :desc]] }).and_return(Person.new(:title => "Sir"))
377
- end
378
-
379
- it "calls find on the collection with the selector and sort options reversed" do
380
- @criteria.order_by([[:title, :asc]])
381
- @criteria.last.should be_a_kind_of(Person)
382
- end
383
-
384
- end
385
-
386
- context "when no documents exist" do
387
-
388
- before do
389
- @collection = mock
390
- Person.should_receive(:collection).and_return(@collection)
391
- @collection.should_receive(:find_one).with(@criteria.selector, { :sort => [[:_id, :desc]] }).and_return(nil)
392
- end
393
-
394
- it "returns nil" do
395
- @criteria.last.should be_nil
396
- end
397
-
398
- end
399
-
400
- context "when no sorting options provided" do
401
-
402
- before do
403
- @collection = mock
404
- Person.should_receive(:collection).and_return(@collection)
405
- @collection.should_receive(:find_one).with(@criteria.selector, { :sort => [[:_id, :desc]] }).and_return({ :title => "Sir" })
406
- end
407
-
408
- it "defaults to sort by id" do
409
- @criteria.last
410
- end
411
-
412
- end
413
-
414
- end
415
-
416
- describe "#limit" do
417
-
418
- context "when value provided" do
419
-
420
- it "adds the limit to the options" do
421
- @criteria.limit(100)
422
- @criteria.options.should == { :limit => 100 }
423
- end
424
-
425
- end
426
-
427
- context "when value not provided" do
428
-
429
- it "defaults to 20" do
430
- @criteria.limit
431
- @criteria.options.should == { :limit => 20 }
432
- end
433
-
434
- end
435
-
436
- it "returns self" do
437
- @criteria.limit.should == @criteria
438
- end
439
-
440
- end
441
-
442
- describe "#not_in" do
443
-
444
- it "adds the exclusion to the selector" do
445
- @criteria.not_in(:title => ["title1", "title2"], :text => ["test"])
446
- @criteria.selector.should == { :title => { "$nin" => ["title1", "title2"] }, :text => { "$nin" => ["test"] } }
447
- end
448
-
449
- it "returns self" do
450
- @criteria.not_in(:title => ["title1"]).should == @criteria
451
- end
452
-
453
- end
454
-
455
- describe "#offset" do
456
-
457
- context "when the per_page option exists" do
458
-
459
- before do
460
- @criteria.extras({ :per_page => 20, :page => 3 })
461
- end
462
-
463
- it "returns the per_page option" do
464
- @criteria.offset.should == 40
465
- end
466
-
467
- end
468
-
469
- context "when the skip option exists" do
470
-
471
- before do
472
- @criteria.extras({ :skip => 20 })
473
- end
474
-
475
- it "returns the skip option" do
476
- @criteria.offset.should == 20
477
- end
478
-
479
- end
480
-
481
- context "when no option exists" do
482
-
483
- context "when page option exists" do
484
-
485
- before do
486
- @criteria.extras({ :page => 2 })
487
- end
488
-
489
- it "adds the skip option to the options and returns it" do
490
- @criteria.offset.should == 20
491
- @criteria.options[:skip].should == 20
492
- end
493
-
494
- end
495
-
496
- context "when page option does not exist" do
497
-
498
- it "returns nil" do
499
- @criteria.offset.should be_nil
500
- @criteria.options[:skip].should be_nil
501
- end
502
-
503
- end
504
-
505
- end
506
-
507
- end
508
-
509
- describe "#one" do
510
-
511
- context "when documents exist" do
512
-
513
- before do
514
- @collection = mock
515
- Person.should_receive(:collection).and_return(@collection)
516
- @collection.should_receive(:find_one).with(@criteria.selector, @criteria.options).and_return(Person.new(:title => "Sir"))
517
- end
518
-
519
- it "calls find on the collection with the selector and options" do
520
- @criteria.one.should be_a_kind_of(Person)
521
- end
522
-
523
- end
524
-
525
- context "when no documents exist" do
526
-
527
- before do
528
- @collection = mock
529
- Person.should_receive(:collection).and_return(@collection)
530
- @collection.should_receive(:find_one).with(@criteria.selector, @criteria.options).and_return(nil)
531
- end
532
-
533
- it "returns nil" do
534
- @criteria.one.should be_nil
535
- end
536
-
537
- end
538
-
539
- end
540
-
541
- describe "#order_by" do
542
-
543
- context "when field names and direction specified" do
544
-
545
- it "adds the sort to the options" do
546
- @criteria.order_by([[:title, :asc], [:text, :desc]])
547
- @criteria.options.should == { :sort => [[:title, :asc], [:text, :desc]] }
548
- end
549
-
550
- end
551
-
552
- it "returns self" do
553
- @criteria.order_by.should == @criteria
554
- end
555
-
556
- end
557
-
558
- describe "#page" do
559
-
560
- context "when the page option exists" do
561
-
562
- before do
563
- @criteria.extras({ :page => 5 })
564
- end
565
-
566
- it "returns the page option" do
567
- @criteria.page.should == 5
568
- end
569
-
9
+ context ".criteria" do
10
+ it "creates a new criteria for the document" do
11
+ CriteriaTest.criteria.should be_a_kind_of(Mongoid::Criteria)
570
12
  end
571
13
 
572
- context "when the page option does not exist" do
573
-
574
- it "returns 1" do
575
- @criteria.page.should == 1
576
- end
577
-
14
+ it "sets the criteria klass" do
15
+ CriteriaTest.criteria.klass.should == CriteriaTest
578
16
  end
579
-
580
17
  end
581
18
 
582
- describe "#paginate" do
19
+ context "criteria delegates" do
20
+ let(:criteria) { stub('criteria').as_null_object }
583
21
 
584
22
  before do
585
- @collection = mock
586
- Person.should_receive(:collection).and_return(@collection)
587
- @criteria.where(:_id => "1").skip(60).limit(20)
588
- @cursor = mock('cursor', :count => 20, :to_a => [])
589
- @collection.should_receive(:find).with({:_id => "1"}, :skip => 60, :limit => 20).and_return(@cursor)
590
- @results = @criteria.paginate
591
- end
592
-
593
- it "executes and paginates the results" do
594
- @results.current_page.should == 4
595
- @results.per_page.should == 20
23
+ CriteriaTest.stub(:criteria).and_return(criteria)
596
24
  end
597
25
 
598
- end
599
-
600
- describe "#per_page" do
601
-
602
- context "when the per_page option exists" do
603
-
604
- before do
605
- @criteria.extras({ :per_page => 10 })
606
- end
607
-
608
- it "returns the per_page option" do
609
- @criteria.per_page.should == 10
610
- end
611
-
612
- end
613
-
614
- context "when the per_page option does not exist" do
615
-
616
- it "returns 1" do
617
- @criteria.per_page.should == 20
618
- end
619
-
620
- end
621
-
622
- end
623
-
624
- describe "#only" do
625
-
626
- context "when args are provided" do
627
-
628
- it "adds the options for limiting by fields" do
629
- @criteria.only(:title, :text)
630
- @criteria.options.should == { :fields => [ :title, :text ] }
631
- end
632
-
633
- it "returns self" do
634
- @criteria.only.should == @criteria
635
- end
636
-
637
- end
638
-
639
- context "when no args provided" do
640
-
641
- it "does not add the field option" do
642
- @criteria.only
643
- @criteria.options[:fields].should be_nil
644
- end
645
-
646
- end
647
-
648
- end
649
-
650
- describe "#skip" do
651
-
652
- context "when value provided" do
653
-
654
- it "adds the skip value to the options" do
655
- @criteria.skip(20)
656
- @criteria.options.should == { :skip => 20 }
657
- end
658
-
659
- end
660
-
661
- context "when value not provided" do
662
-
663
- it "defaults to zero" do
664
- @criteria.skip
665
- @criteria.options.should == { :skip => 0 }
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)
666
30
  end
667
-
668
- end
669
-
670
- it "returns self" do
671
- @criteria.skip.should == @criteria
672
- end
673
-
674
- end
675
-
676
- describe ".translate" do
677
-
678
- context "with a single argument" do
679
-
680
- before do
681
- @id = Mongo::ObjectID.new.to_s
682
- @document = stub
683
- @criteria = mock
684
- end
685
-
686
- it "creates a criteria for a string" do
687
- MongoDoc::Criteria.should_receive(:new).and_return(@criteria)
688
- @criteria.should_receive(:id).with(@id).and_return(@criteria)
689
- @criteria.should_receive(:one).and_return(@document)
690
- MongoDoc::Criteria.translate(Person, @id)
691
- end
692
-
693
- end
694
-
695
- context "multiple arguments" do
696
-
697
- context "when Person, :conditions => {}" do
698
-
699
- before do
700
- @criteria = MongoDoc::Criteria.translate(Person, :conditions => { :title => "Test" })
701
- end
702
-
703
- it "returns a criteria with a selector from the conditions" do
704
- @criteria.selector.should == { :title => "Test" }
705
- end
706
-
707
- it "returns a criteria with klass Person" do
708
- @criteria.klass.should == Person
709
- end
710
-
711
- end
712
-
713
- context "when :all, :conditions => {}" do
714
-
715
- before do
716
- @criteria = MongoDoc::Criteria.translate(Person, :conditions => { :title => "Test" })
717
- end
718
-
719
- it "returns a criteria with a selector from the conditions" do
720
- @criteria.selector.should == { :title => "Test" }
721
- end
722
-
723
- it "returns a criteria with klass Person" do
724
- @criteria.klass.should == Person
725
- end
726
-
727
- end
728
-
729
- context "when :last, :conditions => {}" do
730
-
731
- before do
732
- @criteria = MongoDoc::Criteria.translate(Person, :conditions => { :title => "Test" })
733
- end
734
-
735
- it "returns a criteria with a selector from the conditions" do
736
- @criteria.selector.should == { :title => "Test" }
737
- end
738
-
739
- it "returns a criteria with klass Person" do
740
- @criteria.klass.should == Person
741
- end
742
- end
743
-
744
- context "when options are provided" do
745
-
746
- before do
747
- @criteria = MongoDoc::Criteria.translate(Person, :conditions => { :title => "Test" }, :skip => 10)
748
- end
749
-
750
- it "adds the criteria and the options" do
751
- @criteria.selector.should == { :title => "Test" }
752
- @criteria.options.should == { :skip => 10 }
753
- end
754
- end
755
- end
756
- end
757
-
758
- describe "#where" do
759
-
760
- it "adds the clause to the selector" do
761
- @criteria.where(:title => "Title", :text => "Text")
762
- @criteria.selector.should == { :title => "Title", :text => "Text" }
763
- end
764
-
765
- it "accepts a js where clause" do
766
- @criteria.where("this.a > 3")
767
- @criteria.selector.should == { '$where' => "this.a > 3" }
768
- end
769
-
770
- it "and return self" do
771
- @criteria.where.should == @criteria
772
- end
773
-
774
- it "#and is an alias for where" do
775
- @criteria.and(:title => "Title", :text => "Text")
776
- @criteria.selector.should == { :title => "Title", :text => "Text" }
777
- end
778
-
779
- it "#conditions is an alias for where" do
780
- @criteria.conditions(:title => "Title", :text => "Text")
781
- @criteria.selector.should == { :title => "Title", :text => "Text" }
782
31
  end
783
32
  end
784
33
  end