mongoid 0.11.7 → 0.11.8
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +4 -0
- data/VERSION +1 -1
- data/lib/mongoid/criteria.rb +48 -10
- data/lib/mongoid/extensions/time/conversions.rb +2 -1
- data/lib/mongoid/finders.rb +30 -0
- data/mongoid.gemspec +1 -1
- data/spec/integration/mongoid/criteria_spec.rb +36 -0
- data/spec/unit/mongoid/criteria_spec.rb +55 -3
- data/spec/unit/mongoid/extensions/time/conversions_spec.rb +8 -0
- data/spec/unit/mongoid/finders_spec.rb +28 -0
- metadata +1 -1
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.11.
|
1
|
+
0.11.8
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -422,23 +422,48 @@ module Mongoid #:nodoc:
|
|
422
422
|
end
|
423
423
|
|
424
424
|
SUM_REDUCE = "function(obj, prev) { prev.sum += obj.[field]; }"
|
425
|
-
# Sum the criteria.
|
425
|
+
# Sum the criteria.
|
426
|
+
#
|
427
|
+
# This will take the internally built selector and options
|
426
428
|
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
427
429
|
# collection itself will be retrieved from the class provided, and once the
|
428
430
|
# query has returned it will provided a grouping of keys with sums.
|
429
431
|
#
|
430
432
|
# Example:
|
431
433
|
#
|
432
|
-
# <tt>criteria.
|
434
|
+
# <tt>criteria.sum(:age)</tt>
|
433
435
|
def sum(field)
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
436
|
+
grouped(:sum, field.to_s, SUM_REDUCE)
|
437
|
+
end
|
438
|
+
|
439
|
+
MIN_REDUCE = "function(obj, prev) { if (prev.max > obj.[field]) { prev.max = obj.[field]; } }"
|
440
|
+
# Return the min value for a field.
|
441
|
+
#
|
442
|
+
# This will take the internally built selector and options
|
443
|
+
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
444
|
+
# collection itself will be retrieved from the class provided, and once the
|
445
|
+
# query has returned it will provided a grouping of keys with sums.
|
446
|
+
#
|
447
|
+
# Example:
|
448
|
+
#
|
449
|
+
# <tt>criteria.min(:age)</tt>
|
450
|
+
def min(field)
|
451
|
+
grouped(:min, field.to_s, MIN_REDUCE)
|
452
|
+
end
|
453
|
+
|
454
|
+
MAX_REDUCE = "function(obj, prev) { if (prev.max < obj.[field]) { prev.max = obj.[field]; } }"
|
455
|
+
# Return the max value for a field.
|
456
|
+
#
|
457
|
+
# This will take the internally built selector and options
|
458
|
+
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
459
|
+
# collection itself will be retrieved from the class provided, and once the
|
460
|
+
# query has returned it will provided a grouping of keys with sums.
|
461
|
+
#
|
462
|
+
# Example:
|
463
|
+
#
|
464
|
+
# <tt>criteria.max(:age)</tt>
|
465
|
+
def max(field)
|
466
|
+
grouped(:max, field.to_s, MAX_REDUCE)
|
442
467
|
end
|
443
468
|
|
444
469
|
# Translate the supplied arguments into a +Criteria+ object.
|
@@ -536,5 +561,18 @@ module Mongoid #:nodoc:
|
|
536
561
|
def update_selector(attributes, operator)
|
537
562
|
attributes.each { |key, value| @selector[key] = { operator => value } }; self
|
538
563
|
end
|
564
|
+
|
565
|
+
# Common functionality for grouping operations. Currently used by min, max
|
566
|
+
# and sum. Will gsub the field name in the supplied reduce function.
|
567
|
+
def grouped(start, field, reduce)
|
568
|
+
collection = @klass.collection.group(
|
569
|
+
nil,
|
570
|
+
@selector,
|
571
|
+
{ start => 0 },
|
572
|
+
reduce.gsub("[field]", field),
|
573
|
+
true
|
574
|
+
)
|
575
|
+
collection.first[start.to_s]
|
576
|
+
end
|
539
577
|
end
|
540
578
|
end
|
data/lib/mongoid/finders.rb
CHANGED
@@ -76,6 +76,21 @@ module Mongoid #:nodoc:
|
|
76
76
|
find(:last, *args)
|
77
77
|
end
|
78
78
|
|
79
|
+
# Convenience method for returning the max value of a field.
|
80
|
+
#
|
81
|
+
# Options:
|
82
|
+
#
|
83
|
+
# field: The field to use when calculating the max.
|
84
|
+
#
|
85
|
+
# Example:
|
86
|
+
#
|
87
|
+
# <tt>Person.max(:age)</tt>
|
88
|
+
#
|
89
|
+
# Returns: <tt>Float</tt> max value.
|
90
|
+
def max(field)
|
91
|
+
Criteria.new(self).max(field)
|
92
|
+
end
|
93
|
+
|
79
94
|
# Will execute a +Criteria+ based on the +DynamicFinder+ that gets
|
80
95
|
# generated.
|
81
96
|
#
|
@@ -94,6 +109,21 @@ module Mongoid #:nodoc:
|
|
94
109
|
results ? results : dyna.create(self)
|
95
110
|
end
|
96
111
|
|
112
|
+
# Convenience method for returning the min value of a field.
|
113
|
+
#
|
114
|
+
# Options:
|
115
|
+
#
|
116
|
+
# field: The field to use when calculating the min.
|
117
|
+
#
|
118
|
+
# Example:
|
119
|
+
#
|
120
|
+
# <tt>Person.min(:age)</tt>
|
121
|
+
#
|
122
|
+
# Returns: <tt>Float</tt> min value.
|
123
|
+
def min(field)
|
124
|
+
Criteria.new(self).min(field)
|
125
|
+
end
|
126
|
+
|
97
127
|
# Find all documents in paginated fashion given the supplied arguments.
|
98
128
|
# If no parameters are passed just default to offset 0 and limit 20.
|
99
129
|
#
|
data/mongoid.gemspec
CHANGED
@@ -2,6 +2,42 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Mongoid::Criteria do
|
4
4
|
|
5
|
+
describe "#max" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
10.times do |n|
|
9
|
+
Person.create(:title => "Sir", :age => (n * 10), :aliases => ["D", "Durran"])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
Person.delete_all
|
15
|
+
end
|
16
|
+
|
17
|
+
it "provides sums for all the fields provided" do
|
18
|
+
Person.criteria.max(:age).should == 90.0
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#min" do
|
24
|
+
|
25
|
+
before do
|
26
|
+
10.times do |n|
|
27
|
+
Person.create(:title => "Sir", :age => (n * 10), :aliases => ["D", "Durran"])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
after do
|
32
|
+
Person.delete_all
|
33
|
+
end
|
34
|
+
|
35
|
+
it "provides sums for all the fields provided" do
|
36
|
+
Person.criteria.min(:age).should == 0.0
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
5
41
|
describe "#sum" do
|
6
42
|
|
7
43
|
before do
|
@@ -492,6 +492,27 @@ describe Mongoid::Criteria do
|
|
492
492
|
|
493
493
|
end
|
494
494
|
|
495
|
+
describe "#max" do
|
496
|
+
|
497
|
+
before do
|
498
|
+
@reduce = "function(obj, prev) { if (prev.max < obj.age) { prev.max = obj.age; } }"
|
499
|
+
@collection = mock
|
500
|
+
Person.expects(:collection).returns(@collection)
|
501
|
+
end
|
502
|
+
|
503
|
+
it "calls group on the collection with the aggregate js" do
|
504
|
+
@collection.expects(:group).with(
|
505
|
+
nil,
|
506
|
+
{:_type => { "$in" => ["Doctor", "Person"] } },
|
507
|
+
{:max => 0},
|
508
|
+
@reduce,
|
509
|
+
true
|
510
|
+
).returns([{"max" => 200.0}])
|
511
|
+
@criteria.max(:age).should == 200.0
|
512
|
+
end
|
513
|
+
|
514
|
+
end
|
515
|
+
|
495
516
|
describe "#merge" do
|
496
517
|
|
497
518
|
before do
|
@@ -591,11 +612,36 @@ describe Mongoid::Criteria do
|
|
591
612
|
|
592
613
|
end
|
593
614
|
|
615
|
+
describe "#min" do
|
616
|
+
|
617
|
+
before do
|
618
|
+
@reduce = "function(obj, prev) { if (prev.max > obj.age) { prev.max = obj.age; } }"
|
619
|
+
@collection = mock
|
620
|
+
Person.expects(:collection).returns(@collection)
|
621
|
+
end
|
622
|
+
|
623
|
+
it "calls group on the collection with the aggregate js" do
|
624
|
+
@collection.expects(:group).with(
|
625
|
+
nil,
|
626
|
+
{:_type => { "$in" => ["Doctor", "Person"] } },
|
627
|
+
{:min => 0},
|
628
|
+
@reduce,
|
629
|
+
true
|
630
|
+
).returns([{"min" => 4.0}])
|
631
|
+
@criteria.min(:age).should == 4.0
|
632
|
+
end
|
633
|
+
|
634
|
+
end
|
635
|
+
|
594
636
|
describe "#not_in" do
|
595
637
|
|
596
638
|
it "adds the exclusion to the selector" do
|
597
639
|
@criteria.not_in(:title => ["title1", "title2"], :text => ["test"])
|
598
|
-
@criteria.selector.should == {
|
640
|
+
@criteria.selector.should == {
|
641
|
+
:_type => { "$in" => ["Doctor", "Person"] },
|
642
|
+
:title => { "$nin" => ["title1", "title2"] },
|
643
|
+
:text => { "$nin" => ["test"] }
|
644
|
+
}
|
599
645
|
end
|
600
646
|
|
601
647
|
it "returns self" do
|
@@ -851,8 +897,14 @@ describe Mongoid::Criteria do
|
|
851
897
|
end
|
852
898
|
|
853
899
|
it "calls group on the collection with the aggregate js" do
|
854
|
-
@collection.expects(:group).with(
|
855
|
-
|
900
|
+
@collection.expects(:group).with(
|
901
|
+
nil,
|
902
|
+
{:_type => { "$in" => ["Doctor", "Person"] } },
|
903
|
+
{:sum => 0},
|
904
|
+
@reduce,
|
905
|
+
true
|
906
|
+
).returns([{"sum" => 50.0}])
|
907
|
+
@criteria.sum(:age).should == 50.0
|
856
908
|
end
|
857
909
|
|
858
910
|
end
|
@@ -29,6 +29,14 @@ describe Mongoid::Extensions::Time::Conversions do
|
|
29
29
|
|
30
30
|
end
|
31
31
|
|
32
|
+
context "when value is already a utc time" do
|
33
|
+
|
34
|
+
it "returns the time" do
|
35
|
+
Time.set(@time.utc).should == @time.utc
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
32
40
|
context "when value is nil" do
|
33
41
|
|
34
42
|
it "returns nil" do
|
@@ -197,6 +197,20 @@ describe Mongoid::Finders do
|
|
197
197
|
|
198
198
|
end
|
199
199
|
|
200
|
+
describe ".max" do
|
201
|
+
|
202
|
+
before do
|
203
|
+
@criteria = mock
|
204
|
+
end
|
205
|
+
|
206
|
+
it "returns the sum of a new criteria" do
|
207
|
+
Mongoid::Criteria.expects(:new).returns(@criteria)
|
208
|
+
@criteria.expects(:max).with(:age).returns(50.0)
|
209
|
+
Person.max(:age).should == 50.0
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
200
214
|
describe ".method_missing" do
|
201
215
|
|
202
216
|
context "with a finder method name" do
|
@@ -250,6 +264,20 @@ describe Mongoid::Finders do
|
|
250
264
|
|
251
265
|
end
|
252
266
|
|
267
|
+
describe ".min" do
|
268
|
+
|
269
|
+
before do
|
270
|
+
@criteria = mock
|
271
|
+
end
|
272
|
+
|
273
|
+
it "returns the sum of a new criteria" do
|
274
|
+
Mongoid::Criteria.expects(:new).returns(@criteria)
|
275
|
+
@criteria.expects(:min).with(:age).returns(50.0)
|
276
|
+
Person.min(:age).should == 50.0
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
253
281
|
describe ".paginate" do
|
254
282
|
|
255
283
|
before do
|