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 CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.11.8
2
+ - Added #min and #max to criteria which takes a
3
+ single field argument.
4
+
1
5
  === 0.11.7
2
6
  - Added #sum to criteria which takes a single field
3
7
  to aggregate on. Example: Person.sum(:age) would
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.7
1
+ 0.11.8
@@ -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. This will take the internally built selector and options
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.select(:field1).where(:field1 => "Title").sum</tt>
434
+ # <tt>criteria.sum(:age)</tt>
433
435
  def sum(field)
434
- collection = @klass.collection.group(
435
- @options[:fields],
436
- @selector,
437
- { :sum => 0 },
438
- SUM_REDUCE.gsub("[field]", field.to_s),
439
- true
440
- )
441
- collection.first["sum"]
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
@@ -5,7 +5,8 @@ module Mongoid #:nodoc:
5
5
  module Conversions #:nodoc:
6
6
  def set(value)
7
7
  return nil if value.blank?
8
- ::Time.parse(value.to_s).utc
8
+ time = ::Time.parse(value.to_s)
9
+ time.utc? ? time : time.utc
9
10
  end
10
11
  def get(value)
11
12
  return nil if value.blank?
@@ -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
  #
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid}
8
- s.version = "0.11.7"
8
+ s.version = "0.11.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Durran Jordan"]
@@ -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 == { :_type => { "$in" => ["Doctor", "Person"] }, :title => { "$nin" => ["title1", "title2"] }, :text => { "$nin" => ["test"] } }
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(nil, {:_type => { "$in" => ["Doctor", "Person"] }}, {:sum => 0}, @reduce, true).returns([{"sum" => 50.0}])
855
- @criteria.sum(:age)
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.7
4
+ version: 0.11.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Durran Jordan