mongoid 2.2.6 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +2 -858
- data/Rakefile +2 -5
- data/lib/mongoid.rb +1 -1
- data/lib/mongoid/attributes.rb +68 -18
- data/lib/mongoid/attributes/processing.rb +4 -3
- data/lib/mongoid/callbacks.rb +102 -0
- data/lib/mongoid/collection.rb +1 -1
- data/lib/mongoid/components.rb +2 -1
- data/lib/mongoid/contexts/enumerable.rb +0 -24
- data/lib/mongoid/contexts/mongo.rb +2 -2
- data/lib/mongoid/copyable.rb +3 -1
- data/lib/mongoid/criteria.rb +18 -10
- data/lib/mongoid/criterion/complex.rb +11 -0
- data/lib/mongoid/criterion/inclusion.rb +38 -7
- data/lib/mongoid/criterion/optional.rb +2 -7
- data/lib/mongoid/criterion/selector.rb +1 -0
- data/lib/mongoid/dirty.rb +19 -0
- data/lib/mongoid/document.rb +16 -12
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +1 -1
- data/lib/mongoid/extensions/object/checks.rb +4 -1
- data/lib/mongoid/extensions/object_id/conversions.rb +4 -2
- data/lib/mongoid/extensions/string/inflections.rb +2 -2
- data/lib/mongoid/factory.rb +7 -2
- data/lib/mongoid/fields.rb +4 -10
- data/lib/mongoid/fields/serializable.rb +18 -2
- data/lib/mongoid/fields/serializable/integer.rb +17 -5
- data/lib/mongoid/fields/serializable/localized.rb +41 -0
- data/lib/mongoid/finders.rb +5 -4
- data/lib/mongoid/hierarchy.rb +87 -84
- data/lib/mongoid/identity.rb +4 -2
- data/lib/mongoid/keys.rb +2 -1
- data/lib/mongoid/logger.rb +1 -7
- data/lib/mongoid/matchers/and.rb +30 -0
- data/lib/mongoid/matchers/in.rb +1 -1
- data/lib/mongoid/matchers/nin.rb +1 -1
- data/lib/mongoid/matchers/strategies.rb +6 -4
- data/lib/mongoid/multi_parameter_attributes.rb +3 -2
- data/lib/mongoid/named_scope.rb +3 -13
- data/lib/mongoid/nested_attributes.rb +1 -1
- data/lib/mongoid/paranoia.rb +2 -3
- data/lib/mongoid/persistence.rb +9 -5
- data/lib/mongoid/persistence/atomic/operation.rb +1 -1
- data/lib/mongoid/persistence/deletion.rb +1 -1
- data/lib/mongoid/persistence/insertion.rb +1 -1
- data/lib/mongoid/persistence/modification.rb +1 -1
- data/lib/mongoid/railtie.rb +1 -1
- data/lib/mongoid/railties/database.rake +9 -1
- data/lib/mongoid/relations.rb +1 -0
- data/lib/mongoid/relations/accessors.rb +1 -1
- data/lib/mongoid/relations/builders.rb +6 -4
- data/lib/mongoid/relations/builders/referenced/many.rb +1 -23
- data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
- data/lib/mongoid/relations/cascading.rb +5 -3
- data/lib/mongoid/relations/conversions.rb +35 -0
- data/lib/mongoid/relations/embedded/atomic.rb +3 -3
- data/lib/mongoid/relations/embedded/in.rb +1 -1
- data/lib/mongoid/relations/embedded/many.rb +16 -13
- data/lib/mongoid/relations/embedded/one.rb +3 -3
- data/lib/mongoid/relations/metadata.rb +19 -15
- data/lib/mongoid/relations/proxy.rb +4 -5
- data/lib/mongoid/relations/referenced/in.rb +1 -1
- data/lib/mongoid/relations/referenced/many.rb +12 -31
- data/lib/mongoid/relations/referenced/many_to_many.rb +4 -5
- data/lib/mongoid/relations/referenced/one.rb +6 -8
- data/lib/mongoid/relations/synchronization.rb +3 -5
- data/lib/mongoid/safety.rb +34 -4
- data/lib/mongoid/serialization.rb +20 -6
- data/lib/mongoid/threaded.rb +47 -0
- data/lib/mongoid/timestamps.rb +1 -0
- data/lib/mongoid/timestamps/created.rb +1 -8
- data/lib/mongoid/timestamps/timeless.rb +50 -0
- data/lib/mongoid/timestamps/updated.rb +2 -9
- data/lib/mongoid/validations.rb +0 -2
- data/lib/mongoid/validations/associated.rb +1 -2
- data/lib/mongoid/validations/uniqueness.rb +89 -36
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +5 -6
- data/lib/rails/generators/mongoid_generator.rb +1 -1
- data/lib/rails/mongoid.rb +14 -5
- metadata +27 -23
| @@ -32,6 +32,17 @@ module Mongoid #:nodoc: | |
| 32 32 | 
             
                    [@key, @operator].hash
         | 
| 33 33 | 
             
                  end
         | 
| 34 34 |  | 
| 35 | 
            +
                  # Create a mongo query with given value
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # @example Create query
         | 
| 38 | 
            +
                  #   criterion.to_mongo_hash(value)
         | 
| 39 | 
            +
                  #
         | 
| 40 | 
            +
                  # @params [] Whatever is a valid input for given operator
         | 
| 41 | 
            +
                  # @return [ Hash ] The query
         | 
| 42 | 
            +
                  def to_mongo_query(v)
         | 
| 43 | 
            +
                    {"$#{self.operator}" => v}
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 35 46 | 
             
                  # Is the criterion equal to the other?
         | 
| 36 47 | 
             
                  #
         | 
| 37 48 | 
             
                  # @example Check equality.
         | 
| @@ -20,6 +20,27 @@ module Mongoid #:nodoc: | |
| 20 20 | 
             
                  end
         | 
| 21 21 | 
             
                  alias :all_in :all
         | 
| 22 22 |  | 
| 23 | 
            +
                  # Adds a criterion to the criteria that specifies multiple expressions
         | 
| 24 | 
            +
                  # that *all* must match. This uses MongoDB's $and operator under the
         | 
| 25 | 
            +
                  # covers.
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  # @example Match all provided expressions.
         | 
| 28 | 
            +
                  #   criteria.all_of(:name => value, :age.gt => 18)
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # @param [ Array<Hash> ] Multiple hash expressions.
         | 
| 31 | 
            +
                  #
         | 
| 32 | 
            +
                  # @return [ Criteria ] The criteria object.
         | 
| 33 | 
            +
                  #
         | 
| 34 | 
            +
                  # @since 2.3.0
         | 
| 35 | 
            +
                  def all_of(*args)
         | 
| 36 | 
            +
                    clone.tap do |crit|
         | 
| 37 | 
            +
                      criterion = @selector["$and"] || []
         | 
| 38 | 
            +
                      converted = BSON::ObjectId.convert(klass, args.flatten)
         | 
| 39 | 
            +
                      expanded = converted.collect { |hash| hash.expand_complex_criteria }
         | 
| 40 | 
            +
                      crit.selector["$and"] = criterion.concat(expanded)
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 23 44 | 
             
                  # Adds a criterion to the +Criteria+ that specifies values where any can
         | 
| 24 45 | 
             
                  # be matched in order to return results. This is similar to an SQL "IN"
         | 
| 25 46 | 
             
                  # clause. The MongoDB conditional operator that will be used is "$in".
         | 
| @@ -216,14 +237,24 @@ module Mongoid #:nodoc: | |
| 216 237 | 
             
                          BSON::ObjectId.convert(klass, selector || {}, false).expand_complex_criteria
         | 
| 217 238 | 
             
                      end
         | 
| 218 239 |  | 
| 240 | 
            +
                      # @todo: Durran: 3.0.0: refactor the merging into separate strategies
         | 
| 241 | 
            +
                      # to clean this funkiness up.
         | 
| 219 242 | 
             
                      selector.each_pair do |key, value|
         | 
| 220 | 
            -
                        if crit.selector.has_key?(key) | 
| 221 | 
            -
                           | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
                             | 
| 225 | 
            -
                              key  | 
| 243 | 
            +
                        if crit.selector.has_key?(key)
         | 
| 244 | 
            +
                          if key.to_s =~ /^(|_)id$/
         | 
| 245 | 
            +
                            if crit.selector.has_key?("$and")
         | 
| 246 | 
            +
                              crit.selector["$and"] << { key => value }
         | 
| 247 | 
            +
                            else
         | 
| 248 | 
            +
                              crit.selector["$and"] = [{ key => crit.selector.delete(key) }, { key => value }]
         | 
| 226 249 | 
             
                            end
         | 
| 250 | 
            +
                          elsif crit.selector[key].respond_to?(:merge) && value.respond_to?(:merge)
         | 
| 251 | 
            +
                            crit.selector[key] =
         | 
| 252 | 
            +
                              crit.selector[key].merge(value) do |key, old, new|
         | 
| 253 | 
            +
                                key == '$in' ? old & new : new
         | 
| 254 | 
            +
                              end
         | 
| 255 | 
            +
                          else
         | 
| 256 | 
            +
                            crit.selector[key] = value
         | 
| 257 | 
            +
                          end
         | 
| 227 258 | 
             
                        else
         | 
| 228 259 | 
             
                          crit.selector[key] = value
         | 
| 229 260 | 
             
                        end
         | 
| @@ -266,7 +297,7 @@ module Mongoid #:nodoc: | |
| 266 297 | 
             
                  #
         | 
| 267 298 | 
             
                  # @since 2.2.1
         | 
| 268 299 | 
             
                  def from_map_or_db(criteria)
         | 
| 269 | 
            -
                    IdentityMap.get(klass, criteria. | 
| 300 | 
            +
                    IdentityMap.get(klass, criteria.extract_id) || criteria.one
         | 
| 270 301 | 
             
                  end
         | 
| 271 302 | 
             
                end
         | 
| 272 303 | 
             
              end
         | 
| @@ -91,14 +91,9 @@ module Mongoid #:nodoc: | |
| 91 91 | 
             
                  def for_ids(*ids)
         | 
| 92 92 | 
             
                    ids.flatten!
         | 
| 93 93 | 
             
                    if ids.size > 1
         | 
| 94 | 
            -
                       | 
| 95 | 
            -
                        :_id => ::BSON::ObjectId.convert(klass, ids)
         | 
| 96 | 
            -
                      )
         | 
| 94 | 
            +
                      where(:_id.in => ::BSON::ObjectId.convert(klass, ids))
         | 
| 97 95 | 
             
                    else
         | 
| 98 | 
            -
                       | 
| 99 | 
            -
                        crit.selector[:_id] =
         | 
| 100 | 
            -
                          ::BSON::ObjectId.convert(klass, ids.first)
         | 
| 101 | 
            -
                      end
         | 
| 96 | 
            +
                      where(:_id => ids.first)
         | 
| 102 97 | 
             
                    end
         | 
| 103 98 | 
             
                  end
         | 
| 104 99 |  | 
    
        data/lib/mongoid/dirty.rb
    CHANGED
    
    | @@ -108,5 +108,24 @@ module Mongoid #:nodoc: | |
| 108 108 | 
             
                  return false unless changed_attributes.include?(attr)
         | 
| 109 109 | 
             
                  changed_attributes[attr] != attributes[attr]
         | 
| 110 110 | 
             
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                # Override Active Model's behaviour here in order to stay away from
         | 
| 113 | 
            +
                # infinite loops on getter/setter overrides.
         | 
| 114 | 
            +
                #
         | 
| 115 | 
            +
                # @example Flag an attribute as changing.
         | 
| 116 | 
            +
                #   document.attribute_will_change!(:name)
         | 
| 117 | 
            +
                #
         | 
| 118 | 
            +
                # @param [ Symbol ] attr The attribute.
         | 
| 119 | 
            +
                #
         | 
| 120 | 
            +
                # @return [ Object ] The value of the attribute.
         | 
| 121 | 
            +
                #
         | 
| 122 | 
            +
                # @since 2.3.0
         | 
| 123 | 
            +
                def attribute_will_change!(attr)
         | 
| 124 | 
            +
                  unless changed_attributes.include?(attr)
         | 
| 125 | 
            +
                    value = read_attribute(attr)
         | 
| 126 | 
            +
                    value = value.duplicable? ? value.clone : value
         | 
| 127 | 
            +
                    changed_attributes[attr] = value
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                end
         | 
| 111 130 | 
             
              end
         | 
| 112 131 | 
             
            end
         | 
    
        data/lib/mongoid/document.rb
    CHANGED
    
    | @@ -119,15 +119,19 @@ module Mongoid #:nodoc: | |
| 119 119 | 
             
                #   Person.new(:title => "Sir")
         | 
| 120 120 | 
             
                #
         | 
| 121 121 | 
             
                # @param [ Hash ] attrs The attributes to set up the document with.
         | 
| 122 | 
            +
                # @param [ Hash ] options A mass-assignment protection options. Supports
         | 
| 123 | 
            +
                #   :as and :without_protection
         | 
| 122 124 | 
             
                #
         | 
| 123 125 | 
             
                # @return [ Document ] A new document.
         | 
| 124 | 
            -
                def initialize(attrs = nil)
         | 
| 125 | 
            -
                   | 
| 126 | 
            +
                def initialize(attrs = nil, options = nil)
         | 
| 127 | 
            +
                  _building do
         | 
| 126 128 | 
             
                    @new_record = true
         | 
| 127 | 
            -
                    @attributes  | 
| 128 | 
            -
                     | 
| 129 | 
            +
                    @attributes ||= {}
         | 
| 130 | 
            +
                    options ||= {}
         | 
| 131 | 
            +
                    process(attrs, options[:as] || :default, !options[:without_protection]) do
         | 
| 129 132 | 
             
                      yield self if block_given?
         | 
| 130 133 | 
             
                      identify
         | 
| 134 | 
            +
                      apply_defaults
         | 
| 131 135 | 
             
                    end
         | 
| 132 136 | 
             
                    run_callbacks(:initialize) { self }
         | 
| 133 137 | 
             
                  end
         | 
| @@ -150,7 +154,7 @@ module Mongoid #:nodoc: | |
| 150 154 | 
             
                  end
         | 
| 151 155 | 
             
                  @attributes = {}.merge(reloaded || {})
         | 
| 152 156 | 
             
                  changed_attributes.clear
         | 
| 153 | 
            -
                   | 
| 157 | 
            +
                  apply_defaults
         | 
| 154 158 | 
             
                  tap do
         | 
| 155 159 | 
             
                    reload_relations
         | 
| 156 160 | 
             
                    run_callbacks(:initialize)
         | 
| @@ -199,13 +203,13 @@ module Mongoid #:nodoc: | |
| 199 203 | 
             
                # @return [ Document ] An instance of the specified class.
         | 
| 200 204 | 
             
                def becomes(klass)
         | 
| 201 205 | 
             
                  unless klass.include?(Mongoid::Document)
         | 
| 202 | 
            -
                    raise ArgumentError,  | 
| 206 | 
            +
                    raise ArgumentError, "A class which includes Mongoid::Document is expected"
         | 
| 203 207 | 
             
                  end
         | 
| 204 | 
            -
                  klass. | 
| 205 | 
            -
                    became.instance_variable_set( | 
| 206 | 
            -
                    became.instance_variable_set( | 
| 207 | 
            -
                    became.instance_variable_set( | 
| 208 | 
            -
                    became. | 
| 208 | 
            +
                  klass.instantiate(frozen? ? attributes.dup : attributes).tap do |became|
         | 
| 209 | 
            +
                    became.instance_variable_set(:@errors, errors)
         | 
| 210 | 
            +
                    became.instance_variable_set(:@new_record, new_record?)
         | 
| 211 | 
            +
                    became.instance_variable_set(:@destroyed, destroyed?)
         | 
| 212 | 
            +
                    became._type = klass.to_s
         | 
| 209 213 | 
             
                  end
         | 
| 210 214 | 
             
                end
         | 
| 211 215 |  | 
| @@ -261,7 +265,7 @@ module Mongoid #:nodoc: | |
| 261 265 | 
             
                    attributes = attrs || {}
         | 
| 262 266 | 
             
                    allocate.tap do |doc|
         | 
| 263 267 | 
             
                      doc.instance_variable_set(:@attributes, attributes)
         | 
| 264 | 
            -
                      doc.send(: | 
| 268 | 
            +
                      doc.send(:apply_defaults)
         | 
| 265 269 | 
             
                      IdentityMap.set(doc)
         | 
| 266 270 | 
             
                      doc.run_callbacks(:initialize) { doc }
         | 
| 267 271 | 
             
                    end
         | 
| @@ -14,6 +14,9 @@ module Mongoid #:nodoc: | |
| 14 14 | 
             
                    # @example Is the array vacant?
         | 
| 15 15 | 
             
                    #   [].vacant?
         | 
| 16 16 | 
             
                    #
         | 
| 17 | 
            +
                    # @example Is the hash vacant?
         | 
| 18 | 
            +
                    #   {}.vacant?
         | 
| 19 | 
            +
                    #
         | 
| 17 20 | 
             
                    # @example Is the object vacant?
         | 
| 18 21 | 
             
                    #   nil.vacant?
         | 
| 19 22 | 
             
                    #
         | 
| @@ -21,7 +24,7 @@ module Mongoid #:nodoc: | |
| 21 24 | 
             
                    #
         | 
| 22 25 | 
             
                    # @since 2.0.2
         | 
| 23 26 | 
             
                    def _vacant?
         | 
| 24 | 
            -
                      is_a?(:: | 
| 27 | 
            +
                      is_a?(::Enumerable) || is_a?(::String) ? empty? : !self
         | 
| 25 28 | 
             
                    end
         | 
| 26 29 | 
             
                  end
         | 
| 27 30 | 
             
                end
         | 
| @@ -38,7 +38,7 @@ module Mongoid #:nodoc: | |
| 38 38 | 
             
                        if args.unconvertable_to_bson?
         | 
| 39 39 | 
             
                          args
         | 
| 40 40 | 
             
                        else
         | 
| 41 | 
            -
                          BSON::ObjectId. | 
| 41 | 
            +
                          BSON::ObjectId.from_string(args)
         | 
| 42 42 | 
             
                        end
         | 
| 43 43 | 
             
                      when ::Array
         | 
| 44 44 | 
             
                        args.delete_if { |arg| arg.blank? } if reject_blank
         | 
| @@ -47,7 +47,9 @@ module Mongoid #:nodoc: | |
| 47 47 | 
             
                        args.tap do |hash|
         | 
| 48 48 | 
             
                          hash.each_pair do |key, value|
         | 
| 49 49 | 
             
                            next unless klass.object_id_field?(key)
         | 
| 50 | 
            -
                             | 
| 50 | 
            +
                            begin
         | 
| 51 | 
            +
                              hash[key] = convert(klass, value, reject_blank)
         | 
| 52 | 
            +
                            rescue BSON::InvalidObjectId; end
         | 
| 51 53 | 
             
                          end
         | 
| 52 54 | 
             
                        end
         | 
| 53 55 | 
             
                      else
         | 
| @@ -18,7 +18,7 @@ module Mongoid #:nodoc: | |
| 18 18 | 
             
                    CHAR_CONV = {
         | 
| 19 19 | 
             
                      " " => "-",
         | 
| 20 20 | 
             
                      "!" => "-excl-",
         | 
| 21 | 
            -
                      "\"" => "- | 
| 21 | 
            +
                      "\"" => "-bckslsh-",
         | 
| 22 22 | 
             
                      "#" => "-hash-",
         | 
| 23 23 | 
             
                      "$" => "-dol-",
         | 
| 24 24 | 
             
                      "%" => "-perc-",
         | 
| @@ -48,7 +48,7 @@ module Mongoid #:nodoc: | |
| 48 48 | 
             
                      "{" => "-ocurly-",
         | 
| 49 49 | 
             
                      "|" => "-pipe-",
         | 
| 50 50 | 
             
                      "}" => "-clcurly-",
         | 
| 51 | 
            -
                      "~" => "- | 
| 51 | 
            +
                      "~" => "-tilda-"
         | 
| 52 52 | 
             
                    }
         | 
| 53 53 |  | 
| 54 54 | 
             
                    REVERSALS = {
         | 
    
        data/lib/mongoid/factory.rb
    CHANGED
    
    | @@ -12,11 +12,16 @@ module Mongoid #:nodoc: | |
| 12 12 | 
             
                #
         | 
| 13 13 | 
             
                # @param [ Class ] klass The class to instantiate from if _type is not present.
         | 
| 14 14 | 
             
                # @param [ Hash ] attributes The document attributes.
         | 
| 15 | 
            +
                # @param [ Hash ] optiosn The mass assignment scoping options.
         | 
| 15 16 | 
             
                #
         | 
| 16 17 | 
             
                # @return [ Document ] The instantiated document.
         | 
| 17 | 
            -
                def build(klass, attributes = {})
         | 
| 18 | 
            +
                def build(klass, attributes = {}, options = {})
         | 
| 18 19 | 
             
                  type = (attributes || {})["_type"]
         | 
| 19 | 
            -
                   | 
| 20 | 
            +
                  if type && klass._types.include?(type)
         | 
| 21 | 
            +
                    type.constantize.new(attributes, options)
         | 
| 22 | 
            +
                  else
         | 
| 23 | 
            +
                    klass.new(attributes, options)
         | 
| 24 | 
            +
                  end
         | 
| 20 25 | 
             
                end
         | 
| 21 26 |  | 
| 22 27 | 
             
                # Builds a new +Document+ from the supplied attributes loaded from the
         | 
    
        data/lib/mongoid/fields.rb
    CHANGED
    
    | @@ -13,6 +13,7 @@ require "mongoid/fields/serializable/hash" | |
| 13 13 | 
             
            require "mongoid/fields/serializable/integer"
         | 
| 14 14 | 
             
            require "mongoid/fields/serializable/bignum"
         | 
| 15 15 | 
             
            require "mongoid/fields/serializable/fixnum"
         | 
| 16 | 
            +
            require "mongoid/fields/serializable/localized"
         | 
| 16 17 | 
             
            require "mongoid/fields/serializable/nil_class"
         | 
| 17 18 | 
             
            require "mongoid/fields/serializable/object"
         | 
| 18 19 | 
             
            require "mongoid/fields/serializable/object_id"
         | 
| @@ -227,20 +228,13 @@ module Mongoid #:nodoc | |
| 227 228 | 
             
                  # @param [ Hash ] options The hash of options.
         | 
| 228 229 | 
             
                  def add_field(name, options = {})
         | 
| 229 230 | 
             
                    meth = options.delete(:as) || name
         | 
| 230 | 
            -
                     | 
| 231 | 
            -
             | 
| 232 | 
            -
                    ).instantiate(name, options).tap do |field|
         | 
| 231 | 
            +
                    type = options[:localize] ? Fields::Serializable::Localized : options[:type]
         | 
| 232 | 
            +
                    Mappings.for(type, options[:identity]).instantiate(name, options).tap do |field|
         | 
| 233 233 | 
             
                      fields[name] = field
         | 
| 234 234 | 
             
                      defaults << name unless field.default.nil?
         | 
| 235 235 | 
             
                      create_accessors(name, meth, options)
         | 
| 236 236 | 
             
                      process_options(field)
         | 
| 237 | 
            -
             | 
| 238 | 
            -
                      # @todo Durran: Refactor this once we can depend on at least
         | 
| 239 | 
            -
                      #   ActiveModel greater than 3.0.9. They finally have the ability then
         | 
| 240 | 
            -
                      #   to add attribute methods one at a time. This code will make class
         | 
| 241 | 
            -
                      #   load times extremely slow.
         | 
| 242 | 
            -
                      undefine_attribute_methods
         | 
| 243 | 
            -
                      define_attribute_methods(fields.keys)
         | 
| 237 | 
            +
                      define_attribute_method(name)
         | 
| 244 238 | 
             
                    end
         | 
| 245 239 | 
             
                  end
         | 
| 246 240 |  | 
| @@ -26,7 +26,7 @@ module Mongoid #:nodoc: | |
| 26 26 | 
             
                  extend ActiveSupport::Concern
         | 
| 27 27 |  | 
| 28 28 | 
             
                  # Set readers for the instance variables.
         | 
| 29 | 
            -
                  attr_accessor :default, :label, :name, :options
         | 
| 29 | 
            +
                  attr_accessor :default, :label, :localize, :name, :options
         | 
| 30 30 |  | 
| 31 31 | 
             
                  # When reading the field do we need to cast the value? This holds true when
         | 
| 32 32 | 
             
                  # times are stored or for big decimals which are stored as strings.
         | 
| @@ -89,6 +89,18 @@ module Mongoid #:nodoc: | |
| 89 89 | 
             
                    end
         | 
| 90 90 | 
             
                  end
         | 
| 91 91 |  | 
| 92 | 
            +
                  # Is the field localized or not?
         | 
| 93 | 
            +
                  #
         | 
| 94 | 
            +
                  # @example Is the field localized?
         | 
| 95 | 
            +
                  #   field.localized?
         | 
| 96 | 
            +
                  #
         | 
| 97 | 
            +
                  # @return [ true, false ] If the field is localized.
         | 
| 98 | 
            +
                  #
         | 
| 99 | 
            +
                  # @since 2.3.0
         | 
| 100 | 
            +
                  def localized?
         | 
| 101 | 
            +
                    !!@localize
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 92 104 | 
             
                  # Get the metadata for the field if its a foreign key.
         | 
| 93 105 | 
             
                  #
         | 
| 94 106 | 
             
                  # @example Get the metadata.
         | 
| @@ -168,8 +180,12 @@ module Mongoid #:nodoc: | |
| 168 180 | 
             
                      allocate.tap do |field|
         | 
| 169 181 | 
             
                        field.name = name
         | 
| 170 182 | 
             
                        field.options = options
         | 
| 171 | 
            -
                        field.default = options[:default]
         | 
| 172 183 | 
             
                        field.label = options[:label]
         | 
| 184 | 
            +
                        field.localize = options[:localize]
         | 
| 185 | 
            +
                        field.default = options[:default]
         | 
| 186 | 
            +
                        unless field.default
         | 
| 187 | 
            +
                          field.default = {} if field.localized?
         | 
| 188 | 
            +
                        end
         | 
| 173 189 | 
             
                      end
         | 
| 174 190 | 
             
                    end
         | 
| 175 191 | 
             
                  end
         | 
| @@ -20,11 +20,23 @@ module Mongoid #:nodoc: | |
| 20 20 | 
             
                    # @since 2.1.0
         | 
| 21 21 | 
             
                    def serialize(object)
         | 
| 22 22 | 
             
                      return nil if object.blank?
         | 
| 23 | 
            -
                       | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 23 | 
            +
                      numeric(object) rescue object
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    # Get the numeric value for the provided object.
         | 
| 29 | 
            +
                    #
         | 
| 30 | 
            +
                    # @example Get the numeric value.
         | 
| 31 | 
            +
                    #   field.numeric("1120")
         | 
| 32 | 
            +
                    #
         | 
| 33 | 
            +
                    # @param [ Object ] object The object to convert.
         | 
| 34 | 
            +
                    #
         | 
| 35 | 
            +
                    # @return [ Integer, Float ] The number.
         | 
| 36 | 
            +
                    #
         | 
| 37 | 
            +
                    # @since 2.3.0
         | 
| 38 | 
            +
                    def numeric(object)
         | 
| 39 | 
            +
                      object.to_s =~ /(^[-+]?[0-9]+$)|(\.0+)$/ ? object.to_i : Float(object)
         | 
| 28 40 | 
             
                    end
         | 
| 29 41 | 
             
                  end
         | 
| 30 42 | 
             
                end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            module Mongoid #:nodoc:
         | 
| 3 | 
            +
              module Fields #:nodoc:
         | 
| 4 | 
            +
                module Serializable #:nodoc:
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  # Defines the behaviour for localized string fields.
         | 
| 7 | 
            +
                  class Localized
         | 
| 8 | 
            +
                    include Serializable
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    # Deserialize the object based on the current locale. Will look in the
         | 
| 11 | 
            +
                    # hash for the current locale.
         | 
| 12 | 
            +
                    #
         | 
| 13 | 
            +
                    # @example Get the deserialized value.
         | 
| 14 | 
            +
                    #   field.deserialize({ "en" => "testing" })
         | 
| 15 | 
            +
                    #
         | 
| 16 | 
            +
                    # @param [ Hash ] object The hash of translations.
         | 
| 17 | 
            +
                    #
         | 
| 18 | 
            +
                    # @return [ String ] The value for the current locale.
         | 
| 19 | 
            +
                    #
         | 
| 20 | 
            +
                    # @since 2.3.0
         | 
| 21 | 
            +
                    def deserialize(object)
         | 
| 22 | 
            +
                      object[::I18n.locale.to_s]
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    # Convert the provided string into a hash for the locale.
         | 
| 26 | 
            +
                    #
         | 
| 27 | 
            +
                    # @example Serialize the value.
         | 
| 28 | 
            +
                    #   field.serialize("testing")
         | 
| 29 | 
            +
                    #
         | 
| 30 | 
            +
                    # @param [ String ] object The string to convert.
         | 
| 31 | 
            +
                    #
         | 
| 32 | 
            +
                    # @return [ Hash ] The locale with string translation.
         | 
| 33 | 
            +
                    #
         | 
| 34 | 
            +
                    # @since 2.3.0
         | 
| 35 | 
            +
                    def serialize(object)
         | 
| 36 | 
            +
                      { ::I18n.locale.to_s => object.try(:to_s) }
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
    
        data/lib/mongoid/finders.rb
    CHANGED
    
    | @@ -7,10 +7,11 @@ module Mongoid #:nodoc: | |
| 7 7 |  | 
| 8 8 | 
             
                # Delegate to the criteria methods that are natural for creating a new
         | 
| 9 9 | 
             
                # criteria.
         | 
| 10 | 
            -
                critera_methods = [ :all_in, :any_in, :any_of, :asc, :ascending, | 
| 11 | 
            -
                                    :desc, :descending, :excludes, | 
| 12 | 
            -
                                    : | 
| 13 | 
            -
                                    : | 
| 10 | 
            +
                critera_methods = [ :all_in, :all_of, :any_in, :any_of, :asc, :ascending,
         | 
| 11 | 
            +
                                    :avg, :desc, :descending, :excludes,
         | 
| 12 | 
            +
                                    :includes, :limit, :max, :min, :not_in, :only,
         | 
| 13 | 
            +
                                    :order_by, :search, :skip, :sum, :without, :where,
         | 
| 14 | 
            +
                                    :update, :update_all, :near ]
         | 
| 14 15 | 
             
                delegate *(critera_methods.dup << { :to => :criteria })
         | 
| 15 16 |  | 
| 16 17 | 
             
                # Find all documents that match the given conditions.
         |