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
 
| 
         @@ -0,0 +1,228 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Mongoid #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Contexts #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Mongo
         
     | 
| 
      
 5 
     | 
    
         
            +
                  include Paging
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :selector, :options, :klass
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  AGGREGATE_REDUCE = "function(obj, prev) { prev.count++; }"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # Aggregate the context. This will take the internally built selector and options
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # query has returned it will provided a grouping of keys with counts.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # <tt>context.aggregate</tt>
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # A +Hash+ with field values as keys, counts as values
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def aggregate
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @klass.collection.group(@options[:fields], @selector, { :count => 0 }, AGGREGATE_REDUCE, true)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # Get the count of matching documents in the database for the context.
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # <tt>context.count</tt>
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # An +Integer+ count of documents.
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def count
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @count ||= @klass.collection.find(@selector, process_options).count
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  GROUP_REDUCE = "function(obj, prev) { prev.group.push(obj); }"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # Groups the context. This will take the internally built selector and options
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 42 
     | 
    
         
            +
                  # query has returned it will provided a grouping of keys with objects.
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # <tt>context.group</tt>
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 49 
     | 
    
         
            +
                  #
         
     | 
| 
      
 50 
     | 
    
         
            +
                  # A +Hash+ with field values as keys, arrays of documents as values.
         
     | 
| 
      
 51 
     | 
    
         
            +
                  def group
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @klass.collection.group(
         
     | 
| 
      
 53 
     | 
    
         
            +
                      @options[:fields],
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @selector,
         
     | 
| 
      
 55 
     | 
    
         
            +
                      { :group => [] },
         
     | 
| 
      
 56 
     | 
    
         
            +
                      GROUP_REDUCE,
         
     | 
| 
      
 57 
     | 
    
         
            +
                      true
         
     | 
| 
      
 58 
     | 
    
         
            +
                    ).collect do |docs|
         
     | 
| 
      
 59 
     | 
    
         
            +
                      docs["group"] = docs["group"].collect do |attrs|
         
     | 
| 
      
 60 
     | 
    
         
            +
                        instantiate(attrs)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
                      docs
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  # Execute the context. This will take the selector and options
         
     | 
| 
      
 67 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +find()+ method on the collection. The
         
     | 
| 
      
 68 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 69 
     | 
    
         
            +
                  # query has returned new documents of the type of class provided will be instantiated.
         
     | 
| 
      
 70 
     | 
    
         
            +
                  #
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # <tt>mongo.execute</tt>
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 76 
     | 
    
         
            +
                  #
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # An +Array+ of documents
         
     | 
| 
      
 78 
     | 
    
         
            +
                  def execute
         
     | 
| 
      
 79 
     | 
    
         
            +
                    attributes = @klass.collection.find(@selector, process_options)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    if attributes
         
     | 
| 
      
 81 
     | 
    
         
            +
                      @count = attributes.count
         
     | 
| 
      
 82 
     | 
    
         
            +
                      attributes.collect { |doc| instantiate(doc) }
         
     | 
| 
      
 83 
     | 
    
         
            +
                    else
         
     | 
| 
      
 84 
     | 
    
         
            +
                      []
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # Create the new mongo context. This will execute the queries given the
         
     | 
| 
      
 89 
     | 
    
         
            +
                  # selector and options against the database.
         
     | 
| 
      
 90 
     | 
    
         
            +
                  #
         
     | 
| 
      
 91 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 92 
     | 
    
         
            +
                  #
         
     | 
| 
      
 93 
     | 
    
         
            +
                  # <tt>Mongoid::Contexts::Mongo.new(selector, options, klass)</tt>
         
     | 
| 
      
 94 
     | 
    
         
            +
                  def initialize(selector, options, klass)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    @selector, @options, @klass = selector, options, klass
         
     | 
| 
      
 96 
     | 
    
         
            +
                    if klass.hereditary
         
     | 
| 
      
 97 
     | 
    
         
            +
                      @hereditary = true
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  # Return the last result for the +Context+. Essentially does a find_one on
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # the collection with the sorting reversed. If no sorting parameters have
         
     | 
| 
      
 103 
     | 
    
         
            +
                  # been provided it will default to ids.
         
     | 
| 
      
 104 
     | 
    
         
            +
                  #
         
     | 
| 
      
 105 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 106 
     | 
    
         
            +
                  #
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # <tt>context.last</tt>
         
     | 
| 
      
 108 
     | 
    
         
            +
                  #
         
     | 
| 
      
 109 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 110 
     | 
    
         
            +
                  #
         
     | 
| 
      
 111 
     | 
    
         
            +
                  # The last document in the collection.
         
     | 
| 
      
 112 
     | 
    
         
            +
                  def last
         
     | 
| 
      
 113 
     | 
    
         
            +
                    opts = process_options
         
     | 
| 
      
 114 
     | 
    
         
            +
                    sorting = opts[:sort]
         
     | 
| 
      
 115 
     | 
    
         
            +
                    sorting = [[:_id, :asc]] unless sorting
         
     | 
| 
      
 116 
     | 
    
         
            +
                    opts[:sort] = sorting.collect { |option| [ option[0], option[1].invert ] }
         
     | 
| 
      
 117 
     | 
    
         
            +
                    attributes = @klass.collection.find_one(@selector, opts)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    attributes ? instantiate(attributes) : nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                  MAX_REDUCE = "function(obj, prev) { if (prev.max == 'start') { prev.max = obj.[field]; } " +
         
     | 
| 
      
 122 
     | 
    
         
            +
                    "if (prev.max < obj.[field]) { prev.max = obj.[field]; } }"
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # Return the max value for a field.
         
     | 
| 
      
 124 
     | 
    
         
            +
                  #
         
     | 
| 
      
 125 
     | 
    
         
            +
                  # This will take the internally built selector and options
         
     | 
| 
      
 126 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #
         
     | 
| 
      
 130 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 131 
     | 
    
         
            +
                  #
         
     | 
| 
      
 132 
     | 
    
         
            +
                  # <tt>context.max(:age)</tt>
         
     | 
| 
      
 133 
     | 
    
         
            +
                  #
         
     | 
| 
      
 134 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 135 
     | 
    
         
            +
                  #
         
     | 
| 
      
 136 
     | 
    
         
            +
                  # A numeric max value.
         
     | 
| 
      
 137 
     | 
    
         
            +
                  def max(field)
         
     | 
| 
      
 138 
     | 
    
         
            +
                    grouped(:max, field.to_s, MAX_REDUCE)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  MIN_REDUCE = "function(obj, prev) { if (prev.min == 'start') { prev.min = obj.[field]; } " +
         
     | 
| 
      
 142 
     | 
    
         
            +
                    "if (prev.min > obj.[field]) { prev.min = obj.[field]; } }"
         
     | 
| 
      
 143 
     | 
    
         
            +
                  # Return the min value for a field.
         
     | 
| 
      
 144 
     | 
    
         
            +
                  #
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # This will take the internally built selector and options
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 148 
     | 
    
         
            +
                  # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
      
 149 
     | 
    
         
            +
                  #
         
     | 
| 
      
 150 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 151 
     | 
    
         
            +
                  #
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # <tt>context.min(:age)</tt>
         
     | 
| 
      
 153 
     | 
    
         
            +
                  #
         
     | 
| 
      
 154 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 155 
     | 
    
         
            +
                  #
         
     | 
| 
      
 156 
     | 
    
         
            +
                  # A numeric minimum value.
         
     | 
| 
      
 157 
     | 
    
         
            +
                  def min(field)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    grouped(:min, field.to_s, MIN_REDUCE)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                  # Return the first result for the +Context+.
         
     | 
| 
      
 162 
     | 
    
         
            +
                  #
         
     | 
| 
      
 163 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 164 
     | 
    
         
            +
                  #
         
     | 
| 
      
 165 
     | 
    
         
            +
                  # <tt>context.one</tt>
         
     | 
| 
      
 166 
     | 
    
         
            +
                  #
         
     | 
| 
      
 167 
     | 
    
         
            +
                  # Return:
         
     | 
| 
      
 168 
     | 
    
         
            +
                  #
         
     | 
| 
      
 169 
     | 
    
         
            +
                  # The first document in the collection.
         
     | 
| 
      
 170 
     | 
    
         
            +
                  def one
         
     | 
| 
      
 171 
     | 
    
         
            +
                    attributes = @klass.collection.find_one(@selector, process_options)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    attributes ? instantiate(attributes) : nil
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                  alias :first :one
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                  SUM_REDUCE = "function(obj, prev) { if (prev.sum == 'start') { prev.sum = 0; } prev.sum += obj.[field]; }"
         
     | 
| 
      
 178 
     | 
    
         
            +
                  # Sum the context.
         
     | 
| 
      
 179 
     | 
    
         
            +
                  #
         
     | 
| 
      
 180 
     | 
    
         
            +
                  # This will take the internally built selector and options
         
     | 
| 
      
 181 
     | 
    
         
            +
                  # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
      
 182 
     | 
    
         
            +
                  # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
      
 183 
     | 
    
         
            +
                  # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
      
 184 
     | 
    
         
            +
                  #
         
     | 
| 
      
 185 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 186 
     | 
    
         
            +
                  #
         
     | 
| 
      
 187 
     | 
    
         
            +
                  # <tt>context.sum(:age)</tt>
         
     | 
| 
      
 188 
     | 
    
         
            +
                  #
         
     | 
| 
      
 189 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 190 
     | 
    
         
            +
                  #
         
     | 
| 
      
 191 
     | 
    
         
            +
                  # A numeric value that is the sum.
         
     | 
| 
      
 192 
     | 
    
         
            +
                  def sum(field)
         
     | 
| 
      
 193 
     | 
    
         
            +
                    grouped(:sum, field.to_s, SUM_REDUCE)
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 197 
     | 
    
         
            +
                  # Common functionality for grouping operations. Currently used by min, max
         
     | 
| 
      
 198 
     | 
    
         
            +
                  # and sum. Will gsub the field name in the supplied reduce function.
         
     | 
| 
      
 199 
     | 
    
         
            +
                  def grouped(start, field, reduce)
         
     | 
| 
      
 200 
     | 
    
         
            +
                    collection = @klass.collection.group(
         
     | 
| 
      
 201 
     | 
    
         
            +
                      nil,
         
     | 
| 
      
 202 
     | 
    
         
            +
                      @selector,
         
     | 
| 
      
 203 
     | 
    
         
            +
                      { start => "start" },
         
     | 
| 
      
 204 
     | 
    
         
            +
                      reduce.gsub("[field]", field),
         
     | 
| 
      
 205 
     | 
    
         
            +
                      true
         
     | 
| 
      
 206 
     | 
    
         
            +
                    )
         
     | 
| 
      
 207 
     | 
    
         
            +
                    collection.first[start.to_s]
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                  # If hereditary instantiate by _type otherwise use the klass.
         
     | 
| 
      
 211 
     | 
    
         
            +
                  def instantiate(attrs)
         
     | 
| 
      
 212 
     | 
    
         
            +
                    @hereditary ? attrs["_type"].constantize.instantiate(attrs) : @klass.instantiate(attrs)
         
     | 
| 
      
 213 
     | 
    
         
            +
                  end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                  # Filters the field list. If no fields have been supplied, then it will be
         
     | 
| 
      
 216 
     | 
    
         
            +
                  # empty. If fields have been defined then _type will be included as well.
         
     | 
| 
      
 217 
     | 
    
         
            +
                  def process_options
         
     | 
| 
      
 218 
     | 
    
         
            +
                    fields = @options[:fields]
         
     | 
| 
      
 219 
     | 
    
         
            +
                    if fields && fields.size > 0 && !fields.include?(:_type)
         
     | 
| 
      
 220 
     | 
    
         
            +
                      fields << :_type
         
     | 
| 
      
 221 
     | 
    
         
            +
                      @options[:fields] = fields
         
     | 
| 
      
 222 
     | 
    
         
            +
                    end
         
     | 
| 
      
 223 
     | 
    
         
            +
                    @options.dup
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
              end
         
     | 
| 
      
 228 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Mongoid #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Contexts #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
                module Paging
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # Paginates the documents.
         
     | 
| 
      
 6 
     | 
    
         
            +
                  #
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # <tt>context.paginate</tt>
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # A collection of documents paginated.
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def paginate
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @collection ||= execute
         
     | 
| 
      
 16 
     | 
    
         
            +
                    WillPaginate::Collection.create(page, per_page, count) do |pager|
         
     | 
| 
      
 17 
     | 
    
         
            +
                      pager.replace(@collection)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  # Either returns the page option and removes it from the options, or
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # returns a default value of 1.
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # An +Integer+ page number.
         
     | 
| 
      
 27 
     | 
    
         
            +
                  def page
         
     | 
| 
      
 28 
     | 
    
         
            +
                    skips, limits = @options[:skip], @options[:limit]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    (skips && limits) ? (skips + limits) / limits : 1
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # Get the number of results per page or the default of 20.
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # Returns:
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # The +Integer+ number of documents in each page.
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def per_page
         
     | 
| 
      
 38 
     | 
    
         
            +
                    (@options[:limit] || 20).to_i
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/mongoid/criteria.rb
    CHANGED
    
    | 
         @@ -17,8 +17,36 @@ module Mongoid #:nodoc: 
     | 
|
| 
       17 
17 
     | 
    
         
             
              class Criteria
         
     | 
| 
       18 
18 
     | 
    
         
             
                include Enumerable
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                attr_accessor :documents
         
     | 
| 
       20 
21 
     | 
    
         
             
                attr_reader :klass, :options, :selector
         
     | 
| 
       21 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
                delegate \
         
     | 
| 
      
 24 
     | 
    
         
            +
                  :aggregate,
         
     | 
| 
      
 25 
     | 
    
         
            +
                  :count,
         
     | 
| 
      
 26 
     | 
    
         
            +
                  :execute,
         
     | 
| 
      
 27 
     | 
    
         
            +
                  :first,
         
     | 
| 
      
 28 
     | 
    
         
            +
                  :group,
         
     | 
| 
      
 29 
     | 
    
         
            +
                  :last,
         
     | 
| 
      
 30 
     | 
    
         
            +
                  :max,
         
     | 
| 
      
 31 
     | 
    
         
            +
                  :min,
         
     | 
| 
      
 32 
     | 
    
         
            +
                  :one,
         
     | 
| 
      
 33 
     | 
    
         
            +
                  :page,
         
     | 
| 
      
 34 
     | 
    
         
            +
                  :paginate,
         
     | 
| 
      
 35 
     | 
    
         
            +
                  :per_page,
         
     | 
| 
      
 36 
     | 
    
         
            +
                  :sum, :to => :context
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # Concatinate the criteria with another enumerable. If the other is a
         
     | 
| 
      
 39 
     | 
    
         
            +
                # +Criteria+ then it needs to get the collection from it.
         
     | 
| 
      
 40 
     | 
    
         
            +
                def +(other)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  entries + (other.is_a?(Criteria) ? other.entries : other)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                # Returns the difference between the criteria and another enumerable. If
         
     | 
| 
      
 45 
     | 
    
         
            +
                # the other is a +Criteria+ then it needs to get the collection from it.
         
     | 
| 
      
 46 
     | 
    
         
            +
                def -(other)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  entries - (other.is_a?(Criteria) ? other.entries : other)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       22 
50 
     | 
    
         
             
                # Returns true if the supplied +Enumerable+ or +Criteria+ is equal to the results
         
     | 
| 
       23 
51 
     | 
    
         
             
                # of this +Criteria+ or the criteria itself.
         
     | 
| 
       24 
52 
     | 
    
         
             
                #
         
     | 
| 
         @@ -39,19 +67,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       39 
67 
     | 
    
         
             
                  end
         
     | 
| 
       40 
68 
     | 
    
         
             
                end
         
     | 
| 
       41 
69 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                AGGREGATE_REDUCE = "function(obj, prev) { prev.count++; }"
         
     | 
| 
       43 
     | 
    
         
            -
                # Aggregate the criteria. This will take the internally built selector and options
         
     | 
| 
       44 
     | 
    
         
            -
                # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
       45 
     | 
    
         
            -
                # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
       46 
     | 
    
         
            -
                # query has returned it will provided a grouping of keys with counts.
         
     | 
| 
       47 
     | 
    
         
            -
                #
         
     | 
| 
       48 
     | 
    
         
            -
                # Example:
         
     | 
| 
       49 
     | 
    
         
            -
                #
         
     | 
| 
       50 
     | 
    
         
            -
                # <tt>criteria.select(:field1).where(:field1 => "Title").aggregate(Person)</tt>
         
     | 
| 
       51 
     | 
    
         
            -
                def aggregate
         
     | 
| 
       52 
     | 
    
         
            -
                  @klass.collection.group(@options[:fields], @selector, { :count => 0 }, AGGREGATE_REDUCE, true)
         
     | 
| 
       53 
     | 
    
         
            -
                end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
70 
     | 
    
         
             
                # Adds a criterion to the +Criteria+ that specifies values that must all
         
     | 
| 
       56 
71 
     | 
    
         
             
                # be matched in order to return results. Similar to an "in" clause but the
         
     | 
| 
       57 
72 
     | 
    
         
             
                # underlying conditional logic is an "AND" and not an "OR". The MongoDB
         
     | 
| 
         @@ -92,15 +107,12 @@ module Mongoid #:nodoc: 
     | 
|
| 
       92 
107 
     | 
    
         
             
                  where(selector)
         
     | 
| 
       93 
108 
     | 
    
         
             
                end
         
     | 
| 
       94 
109 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                #  
     | 
| 
       96 
     | 
    
         
            -
                #
         
     | 
| 
       97 
     | 
    
         
            -
                # Example:
         
     | 
| 
       98 
     | 
    
         
            -
                #
         
     | 
| 
       99 
     | 
    
         
            -
                # <tt>criteria.count</tt>
         
     | 
| 
      
 110 
     | 
    
         
            +
                # Return or create the context in which this criteria should be executed.
         
     | 
| 
       100 
111 
     | 
    
         
             
                #
         
     | 
| 
       101 
     | 
    
         
            -
                #  
     | 
| 
       102 
     | 
    
         
            -
                 
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
      
 112 
     | 
    
         
            +
                # This will return an Enumerable context if the class is embedded,
         
     | 
| 
      
 113 
     | 
    
         
            +
                # otherwise it will return a Mongo context for root classes.
         
     | 
| 
      
 114 
     | 
    
         
            +
                def context
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @context ||= determine_context
         
     | 
| 
       104 
116 
     | 
    
         
             
                end
         
     | 
| 
       105 
117 
     | 
    
         | 
| 
       106 
118 
     | 
    
         
             
                # Merges the supplied argument hash into a single criteria
         
     | 
| 
         @@ -167,30 +179,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       167 
179 
     | 
    
         
             
                  @options = extras; filter_options; self
         
     | 
| 
       168 
180 
     | 
    
         
             
                end
         
     | 
| 
       169 
181 
     | 
    
         | 
| 
       170 
     | 
    
         
            -
                GROUP_REDUCE = "function(obj, prev) { prev.group.push(obj); }"
         
     | 
| 
       171 
     | 
    
         
            -
                # Groups the criteria. This will take the internally built selector and options
         
     | 
| 
       172 
     | 
    
         
            -
                # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
       173 
     | 
    
         
            -
                # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
       174 
     | 
    
         
            -
                # query has returned it will provided a grouping of keys with objects.
         
     | 
| 
       175 
     | 
    
         
            -
                #
         
     | 
| 
       176 
     | 
    
         
            -
                # Example:
         
     | 
| 
       177 
     | 
    
         
            -
                #
         
     | 
| 
       178 
     | 
    
         
            -
                # <tt>criteria.select(:field1).where(:field1 => "Title").group(Person)</tt>
         
     | 
| 
       179 
     | 
    
         
            -
                def group
         
     | 
| 
       180 
     | 
    
         
            -
                  @klass.collection.group(
         
     | 
| 
       181 
     | 
    
         
            -
                    @options[:fields],
         
     | 
| 
       182 
     | 
    
         
            -
                    @selector,
         
     | 
| 
       183 
     | 
    
         
            -
                    { :group => [] },
         
     | 
| 
       184 
     | 
    
         
            -
                    GROUP_REDUCE,
         
     | 
| 
       185 
     | 
    
         
            -
                    true
         
     | 
| 
       186 
     | 
    
         
            -
                  ).collect do |docs|
         
     | 
| 
       187 
     | 
    
         
            -
                    docs["group"] = docs["group"].collect do |attrs|
         
     | 
| 
       188 
     | 
    
         
            -
                      instantiate(attrs)
         
     | 
| 
       189 
     | 
    
         
            -
                    end
         
     | 
| 
       190 
     | 
    
         
            -
                    docs
         
     | 
| 
       191 
     | 
    
         
            -
                  end
         
     | 
| 
       192 
     | 
    
         
            -
                end
         
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
182 
     | 
    
         
             
                # Adds a criterion to the +Criteria+ that specifies values where any can
         
     | 
| 
       195 
183 
     | 
    
         
             
                # be matched in order to return results. This is similar to an SQL "IN"
         
     | 
| 
       196 
184 
     | 
    
         
             
                # clause. The MongoDB conditional operator that will be used is "$in".
         
     | 
| 
         @@ -234,29 +222,13 @@ module Mongoid #:nodoc: 
     | 
|
| 
       234 
222 
     | 
    
         
             
                # type: One of :all, :first:, or :last
         
     | 
| 
       235 
223 
     | 
    
         
             
                # klass: The class to execute on.
         
     | 
| 
       236 
224 
     | 
    
         
             
                def initialize(klass)
         
     | 
| 
       237 
     | 
    
         
            -
                  @selector, @options, @klass = {}, {}, klass
         
     | 
| 
      
 225 
     | 
    
         
            +
                  @selector, @options, @klass, @documents = {}, {}, klass, []
         
     | 
| 
       238 
226 
     | 
    
         
             
                  if klass.hereditary
         
     | 
| 
       239 
227 
     | 
    
         
             
                    @selector = { :_type => { "$in" => klass._types } }
         
     | 
| 
       240 
228 
     | 
    
         
             
                    @hereditary = true
         
     | 
| 
       241 
229 
     | 
    
         
             
                  end
         
     | 
| 
       242 
230 
     | 
    
         
             
                end
         
     | 
| 
       243 
231 
     | 
    
         | 
| 
       244 
     | 
    
         
            -
                # Return the last result for the +Criteria+. Essentially does a find_one on
         
     | 
| 
       245 
     | 
    
         
            -
                # the collection with the sorting reversed. If no sorting parameters have
         
     | 
| 
       246 
     | 
    
         
            -
                # been provided it will default to ids.
         
     | 
| 
       247 
     | 
    
         
            -
                #
         
     | 
| 
       248 
     | 
    
         
            -
                # Example:
         
     | 
| 
       249 
     | 
    
         
            -
                #
         
     | 
| 
       250 
     | 
    
         
            -
                # <tt>Criteria.select(:name).where(:name = "Chrissy").last</tt>
         
     | 
| 
       251 
     | 
    
         
            -
                def last
         
     | 
| 
       252 
     | 
    
         
            -
                  opts = process_options
         
     | 
| 
       253 
     | 
    
         
            -
                  sorting = opts[:sort]
         
     | 
| 
       254 
     | 
    
         
            -
                  sorting = [[:_id, :asc]] unless sorting
         
     | 
| 
       255 
     | 
    
         
            -
                  opts[:sort] = sorting.collect { |option| [ option[0], option[1].invert ] }
         
     | 
| 
       256 
     | 
    
         
            -
                  attributes = @klass.collection.find_one(@selector, opts)
         
     | 
| 
       257 
     | 
    
         
            -
                  attributes ? instantiate(attributes) : nil
         
     | 
| 
       258 
     | 
    
         
            -
                end
         
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
232 
     | 
    
         
             
                # Adds a criterion to the +Criteria+ that specifies the maximum number of
         
     | 
| 
       261 
233 
     | 
    
         
             
                # results to return. This is mostly used in conjunction with <tt>skip()</tt>
         
     | 
| 
       262 
234 
     | 
    
         
             
                # to handle paginated results.
         
     | 
| 
         @@ -274,38 +246,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       274 
246 
     | 
    
         
             
                  @options[:limit] = value; self
         
     | 
| 
       275 
247 
     | 
    
         
             
                end
         
     | 
| 
       276 
248 
     | 
    
         | 
| 
       277 
     | 
    
         
            -
                MIN_REDUCE = "function(obj, prev) { if (prev.min == 'start') { prev.min = obj.[field]; } " +
         
     | 
| 
       278 
     | 
    
         
            -
                  "if (prev.min > obj.[field]) { prev.min = obj.[field]; } }"
         
     | 
| 
       279 
     | 
    
         
            -
                # Return the min value for a field.
         
     | 
| 
       280 
     | 
    
         
            -
                #
         
     | 
| 
       281 
     | 
    
         
            -
                # This will take the internally built selector and options
         
     | 
| 
       282 
     | 
    
         
            -
                # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
       283 
     | 
    
         
            -
                # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
       284 
     | 
    
         
            -
                # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
       285 
     | 
    
         
            -
                #
         
     | 
| 
       286 
     | 
    
         
            -
                # Example:
         
     | 
| 
       287 
     | 
    
         
            -
                #
         
     | 
| 
       288 
     | 
    
         
            -
                # <tt>criteria.min(:age)</tt>
         
     | 
| 
       289 
     | 
    
         
            -
                def min(field)
         
     | 
| 
       290 
     | 
    
         
            -
                  grouped(:min, field.to_s, MIN_REDUCE)
         
     | 
| 
       291 
     | 
    
         
            -
                end
         
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
     | 
    
         
            -
                MAX_REDUCE = "function(obj, prev) { if (prev.max == 'start') { prev.max = obj.[field]; } " +
         
     | 
| 
       294 
     | 
    
         
            -
                  "if (prev.max < obj.[field]) { prev.max = obj.[field]; } }"
         
     | 
| 
       295 
     | 
    
         
            -
                # Return the max value for a field.
         
     | 
| 
       296 
     | 
    
         
            -
                #
         
     | 
| 
       297 
     | 
    
         
            -
                # This will take the internally built selector and options
         
     | 
| 
       298 
     | 
    
         
            -
                # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
       299 
     | 
    
         
            -
                # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
       300 
     | 
    
         
            -
                # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
       301 
     | 
    
         
            -
                #
         
     | 
| 
       302 
     | 
    
         
            -
                # Example:
         
     | 
| 
       303 
     | 
    
         
            -
                #
         
     | 
| 
       304 
     | 
    
         
            -
                # <tt>criteria.max(:age)</tt>
         
     | 
| 
       305 
     | 
    
         
            -
                def max(field)
         
     | 
| 
       306 
     | 
    
         
            -
                  grouped(:max, field.to_s, MAX_REDUCE)
         
     | 
| 
       307 
     | 
    
         
            -
                end
         
     | 
| 
       308 
     | 
    
         
            -
             
     | 
| 
       309 
249 
     | 
    
         
             
                # Merges another object into this +Criteria+. The other object may be a
         
     | 
| 
       310 
250 
     | 
    
         
             
                # +Criteria+ or a +Hash+. This is used to combine multiple scopes together,
         
     | 
| 
       311 
251 
     | 
    
         
             
                # where a chained scope situation may be desired.
         
     | 
| 
         @@ -320,6 +260,7 @@ module Mongoid #:nodoc: 
     | 
|
| 
       320 
260 
     | 
    
         
             
                def merge(other)
         
     | 
| 
       321 
261 
     | 
    
         
             
                  @selector.update(other.selector)
         
     | 
| 
       322 
262 
     | 
    
         
             
                  @options.update(other.options)
         
     | 
| 
      
 263 
     | 
    
         
            +
                  @documents = other.documents
         
     | 
| 
       323 
264 
     | 
    
         
             
                end
         
     | 
| 
       324 
265 
     | 
    
         | 
| 
       325 
266 
     | 
    
         
             
                # Used for chaining +Criteria+ scopes together in the for of class methods
         
     | 
| 
         @@ -357,7 +298,7 @@ module Mongoid #:nodoc: 
     | 
|
| 
       357 
298 
     | 
    
         
             
                    new_scope.merge(self)
         
     | 
| 
       358 
299 
     | 
    
         
             
                    return new_scope
         
     | 
| 
       359 
300 
     | 
    
         
             
                  else
         
     | 
| 
       360 
     | 
    
         
            -
                    return  
     | 
| 
      
 301 
     | 
    
         
            +
                    return entries.send(name, *args)
         
     | 
| 
       361 
302 
     | 
    
         
             
                  end
         
     | 
| 
       362 
303 
     | 
    
         
             
                end
         
     | 
| 
       363 
304 
     | 
    
         | 
| 
         @@ -388,18 +329,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       388 
329 
     | 
    
         
             
                  @options[:skip]
         
     | 
| 
       389 
330 
     | 
    
         
             
                end
         
     | 
| 
       390 
331 
     | 
    
         | 
| 
       391 
     | 
    
         
            -
                # Return the first result for the +Criteria+.
         
     | 
| 
       392 
     | 
    
         
            -
                #
         
     | 
| 
       393 
     | 
    
         
            -
                # Example:
         
     | 
| 
       394 
     | 
    
         
            -
                #
         
     | 
| 
       395 
     | 
    
         
            -
                # <tt>Criteria.select(:name).where(:name = "Chrissy").one</tt>
         
     | 
| 
       396 
     | 
    
         
            -
                def one
         
     | 
| 
       397 
     | 
    
         
            -
                  attributes = @klass.collection.find_one(@selector, process_options)
         
     | 
| 
       398 
     | 
    
         
            -
                  attributes ? instantiate(attributes) : nil
         
     | 
| 
       399 
     | 
    
         
            -
                end
         
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
                alias :first :one
         
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
332 
     | 
    
         
             
                # Adds a criterion to the +Criteria+ that specifies the fields that will
         
     | 
| 
       404 
333 
     | 
    
         
             
                # get returned from the Document. Used mainly for list views that do not
         
     | 
| 
       405 
334 
     | 
    
         
             
                # require all fields to be present. This is similar to SQL "SELECT" values.
         
     | 
| 
         @@ -433,30 +362,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       433 
362 
     | 
    
         
             
                  @options[:sort] = params; self
         
     | 
| 
       434 
363 
     | 
    
         
             
                end
         
     | 
| 
       435 
364 
     | 
    
         | 
| 
       436 
     | 
    
         
            -
                # Either returns the page option and removes it from the options, or
         
     | 
| 
       437 
     | 
    
         
            -
                # returns a default value of 1.
         
     | 
| 
       438 
     | 
    
         
            -
                def page
         
     | 
| 
       439 
     | 
    
         
            -
                  skips, limits = @options[:skip], @options[:limit]
         
     | 
| 
       440 
     | 
    
         
            -
                  (skips && limits) ? (skips + limits) / limits : 1
         
     | 
| 
       441 
     | 
    
         
            -
                end
         
     | 
| 
       442 
     | 
    
         
            -
             
     | 
| 
       443 
     | 
    
         
            -
                # Executes the +Criteria+ and paginates the results.
         
     | 
| 
       444 
     | 
    
         
            -
                #
         
     | 
| 
       445 
     | 
    
         
            -
                # Example:
         
     | 
| 
       446 
     | 
    
         
            -
                #
         
     | 
| 
       447 
     | 
    
         
            -
                # <tt>criteria.paginate</tt>
         
     | 
| 
       448 
     | 
    
         
            -
                def paginate
         
     | 
| 
       449 
     | 
    
         
            -
                  @collection ||= execute
         
     | 
| 
       450 
     | 
    
         
            -
                  WillPaginate::Collection.create(page, per_page, count) do |pager|
         
     | 
| 
       451 
     | 
    
         
            -
                    pager.replace(@collection)
         
     | 
| 
       452 
     | 
    
         
            -
                  end
         
     | 
| 
       453 
     | 
    
         
            -
                end
         
     | 
| 
       454 
     | 
    
         
            -
             
     | 
| 
       455 
     | 
    
         
            -
                # Returns the number of results per page or the default of 20.
         
     | 
| 
       456 
     | 
    
         
            -
                def per_page
         
     | 
| 
       457 
     | 
    
         
            -
                  (@options[:limit] || 20).to_i
         
     | 
| 
       458 
     | 
    
         
            -
                end
         
     | 
| 
       459 
     | 
    
         
            -
             
     | 
| 
       460 
365 
     | 
    
         
             
                # Returns the selector and options as a +Hash+ that would be passed to a
         
     | 
| 
       461 
366 
     | 
    
         
             
                # scope for use with named scopes.
         
     | 
| 
       462 
367 
     | 
    
         
             
                def scoped
         
     | 
| 
         @@ -481,20 +386,7 @@ module Mongoid #:nodoc: 
     | 
|
| 
       481 
386 
     | 
    
         
             
                  @options[:skip] = value; self
         
     | 
| 
       482 
387 
     | 
    
         
             
                end
         
     | 
| 
       483 
388 
     | 
    
         | 
| 
       484 
     | 
    
         
            -
                 
     | 
| 
       485 
     | 
    
         
            -
                # Sum the criteria.
         
     | 
| 
       486 
     | 
    
         
            -
                #
         
     | 
| 
       487 
     | 
    
         
            -
                # This will take the internally built selector and options
         
     | 
| 
       488 
     | 
    
         
            -
                # and pass them on to the Ruby driver's +group()+ method on the collection. The
         
     | 
| 
       489 
     | 
    
         
            -
                # collection itself will be retrieved from the class provided, and once the
         
     | 
| 
       490 
     | 
    
         
            -
                # query has returned it will provided a grouping of keys with sums.
         
     | 
| 
       491 
     | 
    
         
            -
                #
         
     | 
| 
       492 
     | 
    
         
            -
                # Example:
         
     | 
| 
       493 
     | 
    
         
            -
                #
         
     | 
| 
       494 
     | 
    
         
            -
                # <tt>criteria.sum(:age)</tt>
         
     | 
| 
       495 
     | 
    
         
            -
                def sum(field)
         
     | 
| 
       496 
     | 
    
         
            -
                  grouped(:sum, field.to_s, SUM_REDUCE)
         
     | 
| 
       497 
     | 
    
         
            -
                end
         
     | 
| 
      
 389 
     | 
    
         
            +
                alias :to_ary :to_a
         
     | 
| 
       498 
390 
     | 
    
         | 
| 
       499 
391 
     | 
    
         
             
                # Translate the supplied arguments into a +Criteria+ object.
         
     | 
| 
       500 
392 
     | 
    
         
             
                #
         
     | 
| 
         @@ -554,24 +446,12 @@ module Mongoid #:nodoc: 
     | 
|
| 
       554 
446 
     | 
    
         
             
                end
         
     | 
| 
       555 
447 
     | 
    
         | 
| 
       556 
448 
     | 
    
         
             
                protected
         
     | 
| 
       557 
     | 
    
         
            -
                #  
     | 
| 
       558 
     | 
    
         
            -
                 
     | 
| 
       559 
     | 
    
         
            -
             
     | 
| 
       560 
     | 
    
         
            -
             
     | 
| 
       561 
     | 
    
         
            -
                #
         
     | 
| 
       562 
     | 
    
         
            -
                # If this is a +Criteria+ to only find the first object, this will return a
         
     | 
| 
       563 
     | 
    
         
            -
                # single object of the type of class provided.
         
     | 
| 
       564 
     | 
    
         
            -
                #
         
     | 
| 
       565 
     | 
    
         
            -
                # If this is a +Criteria+ to find multiple results, will return an +Array+ of
         
     | 
| 
       566 
     | 
    
         
            -
                # objects of the type of class provided.
         
     | 
| 
       567 
     | 
    
         
            -
                def execute
         
     | 
| 
       568 
     | 
    
         
            -
                  attributes = @klass.collection.find(@selector, process_options)
         
     | 
| 
       569 
     | 
    
         
            -
                  if attributes
         
     | 
| 
       570 
     | 
    
         
            -
                    @count = attributes.count
         
     | 
| 
       571 
     | 
    
         
            -
                    attributes.collect { |doc| instantiate(doc) }
         
     | 
| 
       572 
     | 
    
         
            -
                  else
         
     | 
| 
       573 
     | 
    
         
            -
                    []
         
     | 
| 
      
 449 
     | 
    
         
            +
                # Determines the context to be used for this criteria.
         
     | 
| 
      
 450 
     | 
    
         
            +
                def determine_context
         
     | 
| 
      
 451 
     | 
    
         
            +
                  if @klass.embedded
         
     | 
| 
      
 452 
     | 
    
         
            +
                    return Contexts::Enumerable.new(@selector, @options, @documents)
         
     | 
| 
       574 
453 
     | 
    
         
             
                  end
         
     | 
| 
      
 454 
     | 
    
         
            +
                  Contexts::Mongo.new(@selector, @options, @klass)
         
     | 
| 
       575 
455 
     | 
    
         
             
                end
         
     | 
| 
       576 
456 
     | 
    
         | 
| 
       577 
457 
     | 
    
         
             
                # Filters the unused options out of the options +Hash+. Currently this
         
     | 
| 
         @@ -586,35 +466,6 @@ module Mongoid #:nodoc: 
     | 
|
| 
       586 
466 
     | 
    
         
             
                  end
         
     | 
| 
       587 
467 
     | 
    
         
             
                end
         
     | 
| 
       588 
468 
     | 
    
         | 
| 
       589 
     | 
    
         
            -
                # Common functionality for grouping operations. Currently used by min, max
         
     | 
| 
       590 
     | 
    
         
            -
                # and sum. Will gsub the field name in the supplied reduce function.
         
     | 
| 
       591 
     | 
    
         
            -
                def grouped(start, field, reduce)
         
     | 
| 
       592 
     | 
    
         
            -
                  collection = @klass.collection.group(
         
     | 
| 
       593 
     | 
    
         
            -
                    nil,
         
     | 
| 
       594 
     | 
    
         
            -
                    @selector,
         
     | 
| 
       595 
     | 
    
         
            -
                    { start => "start" },
         
     | 
| 
       596 
     | 
    
         
            -
                    reduce.gsub("[field]", field),
         
     | 
| 
       597 
     | 
    
         
            -
                    true
         
     | 
| 
       598 
     | 
    
         
            -
                  )
         
     | 
| 
       599 
     | 
    
         
            -
                  collection.first[start.to_s]
         
     | 
| 
       600 
     | 
    
         
            -
                end
         
     | 
| 
       601 
     | 
    
         
            -
             
     | 
| 
       602 
     | 
    
         
            -
                # If hereditary instantiate by _type otherwise use the klass.
         
     | 
| 
       603 
     | 
    
         
            -
                def instantiate(attrs)
         
     | 
| 
       604 
     | 
    
         
            -
                  @hereditary ? attrs["_type"].constantize.instantiate(attrs) : @klass.instantiate(attrs)
         
     | 
| 
       605 
     | 
    
         
            -
                end
         
     | 
| 
       606 
     | 
    
         
            -
             
     | 
| 
       607 
     | 
    
         
            -
                # Filters the field list. If no fields have been supplied, then it will be
         
     | 
| 
       608 
     | 
    
         
            -
                # empty. If fields have been defined then _type will be included as well.
         
     | 
| 
       609 
     | 
    
         
            -
                def process_options
         
     | 
| 
       610 
     | 
    
         
            -
                  fields = @options[:fields]
         
     | 
| 
       611 
     | 
    
         
            -
                  if fields && fields.size > 0 && !fields.include?(:_type)
         
     | 
| 
       612 
     | 
    
         
            -
                    fields << :_type
         
     | 
| 
       613 
     | 
    
         
            -
                    @options[:fields] = fields
         
     | 
| 
       614 
     | 
    
         
            -
                  end
         
     | 
| 
       615 
     | 
    
         
            -
                  @options.dup
         
     | 
| 
       616 
     | 
    
         
            -
                end
         
     | 
| 
       617 
     | 
    
         
            -
             
     | 
| 
       618 
469 
     | 
    
         
             
                # Update the selector setting the operator on the value for each key in the
         
     | 
| 
       619 
470 
     | 
    
         
             
                # supplied attributes +Hash+.
         
     | 
| 
       620 
471 
     | 
    
         
             
                def update_selector(attributes, operator)
         
     |