mongoid 2.1.9 → 2.2.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 +281 -0
- data/{README.rdoc → README.md} +24 -14
- data/Rakefile +1 -1
- data/lib/config/locales/bg.yml +5 -0
- data/lib/config/locales/de.yml +5 -0
- data/lib/config/locales/en-GB.yml +5 -0
- data/lib/config/locales/en.yml +5 -0
- data/lib/config/locales/es.yml +3 -0
- data/lib/config/locales/fr.yml +5 -0
- data/lib/config/locales/hi.yml +5 -0
- data/lib/config/locales/hu.yml +5 -0
- data/lib/config/locales/id.yml +5 -0
- data/lib/config/locales/it.yml +5 -0
- data/lib/config/locales/ja.yml +5 -0
- data/lib/config/locales/kr.yml +5 -0
- data/lib/config/locales/nl.yml +5 -0
- data/lib/config/locales/pl.yml +5 -0
- data/lib/config/locales/pt-BR.yml +5 -0
- data/lib/config/locales/pt.yml +5 -0
- data/lib/config/locales/ro.yml +5 -0
- data/lib/config/locales/ru.yml +5 -0
- data/lib/config/locales/sv.yml +5 -0
- data/lib/config/locales/vi.yml +5 -0
- data/lib/config/locales/zh-CN.yml +5 -0
- data/lib/mongoid/atomic.rb +61 -10
- data/lib/mongoid/atomic/modifiers.rb +156 -24
- data/lib/mongoid/attributes.rb +38 -10
- data/lib/mongoid/collection.rb +21 -3
- data/lib/mongoid/collections.rb +52 -6
- data/lib/mongoid/collections/master.rb +8 -2
- data/lib/mongoid/collections/operations.rb +1 -0
- data/lib/mongoid/config.rb +5 -2
- data/lib/mongoid/config/database.rb +15 -2
- data/lib/mongoid/contexts/mongo.rb +3 -0
- data/lib/mongoid/criteria.rb +27 -3
- data/lib/mongoid/criterion/inclusion.rb +58 -0
- data/lib/mongoid/dirty.rb +2 -0
- data/lib/mongoid/document.rb +23 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/errors/callback.rb +26 -0
- data/lib/mongoid/errors/eager_load.rb +25 -0
- data/lib/mongoid/errors/invalid_find.rb +19 -0
- data/lib/mongoid/extensions.rb +3 -1
- data/lib/mongoid/extensions/object_id/conversions.rb +1 -1
- data/lib/mongoid/extras.rb +12 -2
- data/lib/mongoid/fields.rb +41 -2
- data/lib/mongoid/fields/serializable.rb +36 -0
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +13 -14
- data/lib/mongoid/fields/serializable/foreign_keys/object.rb +13 -14
- data/lib/mongoid/finders.rb +4 -4
- data/lib/mongoid/identity_map.rb +33 -20
- data/lib/mongoid/keys.rb +24 -1
- data/lib/mongoid/nested_attributes.rb +16 -4
- data/lib/mongoid/persistence.rb +50 -6
- data/lib/mongoid/persistence/operations.rb +1 -4
- data/lib/mongoid/persistence/operations/update.rb +3 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +27 -44
- data/lib/mongoid/relations/builders/referenced/many.rb +2 -1
- data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
- data/lib/mongoid/relations/cascading.rb +12 -1
- data/lib/mongoid/relations/embedded/many.rb +11 -4
- data/lib/mongoid/relations/embedded/one.rb +6 -2
- data/lib/mongoid/relations/macros.rb +19 -12
- data/lib/mongoid/relations/metadata.rb +17 -0
- data/lib/mongoid/relations/polymorphic.rb +12 -1
- data/lib/mongoid/relations/proxy.rb +24 -0
- data/lib/mongoid/relations/referenced/in.rb +20 -0
- data/lib/mongoid/relations/referenced/many.rb +30 -6
- data/lib/mongoid/relations/referenced/many_to_many.rb +18 -2
- data/lib/mongoid/relations/referenced/one.rb +19 -0
- data/lib/mongoid/relations/reflections.rb +23 -3
- data/lib/mongoid/relations/targets/enumerable.rb +29 -1
- data/lib/mongoid/serialization.rb +1 -1
- data/lib/mongoid/sharding.rb +12 -2
- data/lib/mongoid/threaded.rb +98 -0
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +12 -2
- metadata +25 -21
    
        data/lib/mongoid/keys.rb
    CHANGED
    
    | @@ -7,13 +7,36 @@ module Mongoid #:nodoc: | |
| 7 7 | 
             
                extend ActiveSupport::Concern
         | 
| 8 8 |  | 
| 9 9 | 
             
                attr_reader :identifier
         | 
| 10 | 
            -
                delegate :primary_key, :using_object_ids?, :to => "self.class"
         | 
| 11 10 |  | 
| 12 11 | 
             
                included do
         | 
| 13 12 | 
             
                  cattr_accessor :primary_key, :using_object_ids
         | 
| 14 13 | 
             
                  self.using_object_ids = true
         | 
| 15 14 | 
             
                end
         | 
| 16 15 |  | 
| 16 | 
            +
                # Get the document's primary key.
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # @note Refactored from using delegate for class load performance.
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                # @example Get the primary key.
         | 
| 21 | 
            +
                #   model.primary_key
         | 
| 22 | 
            +
                #
         | 
| 23 | 
            +
                # @return [ Array ] The primary key
         | 
| 24 | 
            +
                def primary_key
         | 
| 25 | 
            +
                  self.class.primary_key
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # Is the document using object ids?
         | 
| 29 | 
            +
                #
         | 
| 30 | 
            +
                # @note Refactored from using delegate for class load performance.
         | 
| 31 | 
            +
                #
         | 
| 32 | 
            +
                # @example Is the document using object ids?
         | 
| 33 | 
            +
                #   model.using_object_ids?
         | 
| 34 | 
            +
                #
         | 
| 35 | 
            +
                # @return [ true, false ] Using object ids.
         | 
| 36 | 
            +
                def using_object_ids?
         | 
| 37 | 
            +
                  self.class.using_object_ids?
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 17 40 | 
             
                private
         | 
| 18 41 |  | 
| 19 42 | 
             
                # Determines if any field that the document id is composed of has changed.
         | 
| @@ -5,13 +5,23 @@ module Mongoid #:nodoc: | |
| 5 5 | 
             
              module NestedAttributes
         | 
| 6 6 | 
             
                extend ActiveSupport::Concern
         | 
| 7 7 |  | 
| 8 | 
            -
                delegate :nested_attributes, :to => "self.class"
         | 
| 9 | 
            -
             | 
| 10 8 | 
             
                included do
         | 
| 11 9 | 
             
                  class_attribute :nested_attributes
         | 
| 12 10 | 
             
                  self.nested_attributes = []
         | 
| 13 11 | 
             
                end
         | 
| 14 12 |  | 
| 13 | 
            +
                # Get the nested attributes.
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                # @note Refactored from using delegate for class load performance.
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                # @example Get the nested attributes.
         | 
| 18 | 
            +
                #   model.nested_attributes
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                # @return [ Array<String> ] The nested attributes methods.
         | 
| 21 | 
            +
                def nested_attributes
         | 
| 22 | 
            +
                  self.class.nested_attributes
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 15 25 | 
             
                module ClassMethods #:nodoc:
         | 
| 16 26 |  | 
| 17 27 | 
             
                  REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |_, value| value.blank? } }
         | 
| @@ -44,8 +54,10 @@ module Mongoid #:nodoc: | |
| 44 54 | 
             
                    args.each do |name|
         | 
| 45 55 | 
             
                      self.nested_attributes += [ "#{name}_attributes=" ]
         | 
| 46 56 | 
             
                      define_method("#{name}_attributes=") do |attrs|
         | 
| 47 | 
            -
                         | 
| 48 | 
            -
             | 
| 57 | 
            +
                        assigning do
         | 
| 58 | 
            +
                          relation = relations[name.to_s]
         | 
| 59 | 
            +
                          relation.nested_builder(attrs, options).build(self)
         | 
| 60 | 
            +
                        end
         | 
| 49 61 | 
             
                      end
         | 
| 50 62 | 
             
                    end
         | 
| 51 63 | 
             
                  end
         | 
    
        data/lib/mongoid/persistence.rb
    CHANGED
    
    | @@ -67,7 +67,11 @@ module Mongoid #:nodoc: | |
| 67 67 | 
             
                #
         | 
| 68 68 | 
             
                # @return [ true, false ] True if validation passed.
         | 
| 69 69 | 
             
                def save!(options = {})
         | 
| 70 | 
            -
                   | 
| 70 | 
            +
                  unless upsert(options)
         | 
| 71 | 
            +
                    self.class.fail_validate!(self) if errors.any?
         | 
| 72 | 
            +
                    self.class.fail_callback!(self, :save!)
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                  return true
         | 
| 71 75 | 
             
                end
         | 
| 72 76 |  | 
| 73 77 | 
             
                # Update the document in the datbase.
         | 
| @@ -124,7 +128,10 @@ module Mongoid #:nodoc: | |
| 124 128 | 
             
                # @return [ true, false ] True if validation passed.
         | 
| 125 129 | 
             
                def update_attributes!(attributes = {})
         | 
| 126 130 | 
             
                  update_attributes(attributes).tap do |result|
         | 
| 127 | 
            -
                     | 
| 131 | 
            +
                    unless result
         | 
| 132 | 
            +
                      self.class.fail_validate!(self) if errors.any?
         | 
| 133 | 
            +
                      self.class.fail_callback!(self, :update_attributes!)
         | 
| 134 | 
            +
                    end
         | 
| 128 135 | 
             
                  end
         | 
| 129 136 | 
             
                end
         | 
| 130 137 |  | 
| @@ -159,7 +166,9 @@ module Mongoid #:nodoc: | |
| 159 166 | 
             
                  #
         | 
| 160 167 | 
             
                  # @return [ Document ] The newly created document.
         | 
| 161 168 | 
             
                  def create(attributes = {}, &block)
         | 
| 162 | 
            -
                     | 
| 169 | 
            +
                    creating do
         | 
| 170 | 
            +
                      new(attributes, &block).tap { |doc| doc.save }
         | 
| 171 | 
            +
                    end
         | 
| 163 172 | 
             
                  end
         | 
| 164 173 |  | 
| 165 174 | 
             
                  # Create a new document. This will instantiate a new document and
         | 
| @@ -174,9 +183,12 @@ module Mongoid #:nodoc: | |
| 174 183 | 
             
                  #
         | 
| 175 184 | 
             
                  # @return [ Document ] The newly created document.
         | 
| 176 185 | 
             
                  def create!(attributes = {}, &block)
         | 
| 177 | 
            -
                     | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 186 | 
            +
                    creating do
         | 
| 187 | 
            +
                      new(attributes, &block).tap do |doc|
         | 
| 188 | 
            +
                        fail_validate!(doc) if doc.insert.errors.any?
         | 
| 189 | 
            +
                        fail_callback!(doc, :create!) if doc.new?
         | 
| 190 | 
            +
                      end
         | 
| 191 | 
            +
                    end
         | 
| 180 192 | 
             
                  end
         | 
| 181 193 |  | 
| 182 194 | 
             
                  # Delete all documents given the supplied conditions. If no conditions
         | 
| @@ -230,6 +242,38 @@ module Mongoid #:nodoc: | |
| 230 242 | 
             
                  def fail_validate!(document)
         | 
| 231 243 | 
             
                    raise Errors::Validations.new(document)
         | 
| 232 244 | 
             
                  end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  # Raise an error if a callback failed.
         | 
| 247 | 
            +
                  #
         | 
| 248 | 
            +
                  # @example Raise the callback error.
         | 
| 249 | 
            +
                  #   Person.fail_callback!(person, :create!)
         | 
| 250 | 
            +
                  #
         | 
| 251 | 
            +
                  # @param [ Document ] document The document to fail.
         | 
| 252 | 
            +
                  # @param [ Symbol ] method The method being called.
         | 
| 253 | 
            +
                  #
         | 
| 254 | 
            +
                  # @since 2.2.0
         | 
| 255 | 
            +
                  def fail_callback!(document, method)
         | 
| 256 | 
            +
                    raise Errors::Callback.new(document.class, method)
         | 
| 257 | 
            +
                  end
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                  private
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                  # Execute a block in creating mode.
         | 
| 262 | 
            +
                  #
         | 
| 263 | 
            +
                  # @example Execute in creating mode.
         | 
| 264 | 
            +
                  #   creating do
         | 
| 265 | 
            +
                  #     relation.push(doc)
         | 
| 266 | 
            +
                  #   end
         | 
| 267 | 
            +
                  #
         | 
| 268 | 
            +
                  # @return [ Object ] The return value of the block.
         | 
| 269 | 
            +
                  #
         | 
| 270 | 
            +
                  # @since 2.1.0
         | 
| 271 | 
            +
                  def creating
         | 
| 272 | 
            +
                    Threaded.begin_create
         | 
| 273 | 
            +
                    yield
         | 
| 274 | 
            +
                  ensure
         | 
| 275 | 
            +
                    Threaded.exit_create
         | 
| 276 | 
            +
                  end
         | 
| 233 277 | 
             
                end
         | 
| 234 278 | 
             
              end
         | 
| 235 279 | 
             
            end
         | 
| @@ -155,10 +155,7 @@ module Mongoid #:nodoc: | |
| 155 155 | 
             
                  # @since 2.1.0
         | 
| 156 156 | 
             
                  def init_updates
         | 
| 157 157 | 
             
                    document.atomic_updates.tap do |updates|
         | 
| 158 | 
            -
                      conflicts = updates.delete(: | 
| 159 | 
            -
                      if conflicts
         | 
| 160 | 
            -
                        @conflicts = { "$pushAll" => conflicts }
         | 
| 161 | 
            -
                      end
         | 
| 158 | 
            +
                      @conflicts = updates.delete(:conflicts) || {}
         | 
| 162 159 | 
             
                    end
         | 
| 163 160 | 
             
                  end
         | 
| 164 161 |  | 
| @@ -43,7 +43,9 @@ module Mongoid #:nodoc: | |
| 43 43 | 
             
                      prepare do
         | 
| 44 44 | 
             
                        unless updates.empty?
         | 
| 45 45 | 
             
                          collection.update(selector, updates, options)
         | 
| 46 | 
            -
                           | 
| 46 | 
            +
                          conflicts.each_pair do |key, value|
         | 
| 47 | 
            +
                            collection.update(selector, { key => value }, options)
         | 
| 48 | 
            +
                          end
         | 
| 47 49 | 
             
                        end
         | 
| 48 50 | 
             
                      end
         | 
| 49 51 | 
             
                    end
         | 
| @@ -12,13 +12,12 @@ module Mongoid # :nodoc: | |
| 12 12 | 
             
                      # the existing relation, a replacement of the relation with a new
         | 
| 13 13 | 
             
                      # document, or a removal of the relation.
         | 
| 14 14 | 
             
                      #
         | 
| 15 | 
            -
                      #  | 
| 15 | 
            +
                      # @example Build the nested attrs.
         | 
| 16 | 
            +
                      #   many.build(person)
         | 
| 16 17 | 
             
                      #
         | 
| 17 | 
            -
                      #  | 
| 18 | 
            +
                      # @param [ Document ] parent The parent document of the relation.
         | 
| 18 19 | 
             
                      #
         | 
| 19 | 
            -
                      #  | 
| 20 | 
            -
                      #
         | 
| 21 | 
            -
                      # parent: The parent document of the relation.
         | 
| 20 | 
            +
                      # @return [ Array ] The attributes.
         | 
| 22 21 | 
             
                      def build(parent)
         | 
| 23 22 | 
             
                        @existing = parent.send(metadata.name)
         | 
| 24 23 | 
             
                        if over_limit?(attributes)
         | 
| @@ -36,19 +35,12 @@ module Mongoid # :nodoc: | |
| 36 35 | 
             
                      # Create the new builder for nested attributes on one-to-many
         | 
| 37 36 | 
             
                      # relations.
         | 
| 38 37 | 
             
                      #
         | 
| 39 | 
            -
                      #  | 
| 40 | 
            -
                      #
         | 
| 41 | 
            -
                      # <tt>One.new(metadata, attributes, options)</tt>
         | 
| 42 | 
            -
                      #
         | 
| 43 | 
            -
                      # Options:
         | 
| 44 | 
            -
                      #
         | 
| 45 | 
            -
                      # metadata: The relation metadata
         | 
| 46 | 
            -
                      # attributes: The attributes hash to attempt to set.
         | 
| 47 | 
            -
                      # options: The options defined.
         | 
| 38 | 
            +
                      # @example Initialize the builder.
         | 
| 39 | 
            +
                      #   One.new(metadata, attributes, options)
         | 
| 48 40 | 
             
                      #
         | 
| 49 | 
            -
                      #  | 
| 50 | 
            -
                      #
         | 
| 51 | 
            -
                      #  | 
| 41 | 
            +
                      # @param [ Metadata ] metadata The relation metadata.
         | 
| 42 | 
            +
                      # @param [ Hash ] attributes The attributes hash to attempt to set.
         | 
| 43 | 
            +
                      # @param [ Hash ] options The options defined.
         | 
| 52 44 | 
             
                      def initialize(metadata, attributes, options = {})
         | 
| 53 45 | 
             
                        if attributes.respond_to?(:with_indifferent_access)
         | 
| 54 46 | 
             
                          @attributes = attributes.with_indifferent_access.sort do |a, b|
         | 
| @@ -65,17 +57,12 @@ module Mongoid # :nodoc: | |
| 65 57 |  | 
| 66 58 | 
             
                      # Can the existing relation potentially be deleted?
         | 
| 67 59 | 
             
                      #
         | 
| 68 | 
            -
                      #  | 
| 69 | 
            -
                      #
         | 
| 70 | 
            -
                      # <tt>destroyable?({ :_destroy => "1" })</tt>
         | 
| 71 | 
            -
                      #
         | 
| 72 | 
            -
                      # Options:
         | 
| 73 | 
            -
                      #
         | 
| 74 | 
            -
                      # attributes: The attributes to pull the flag from.
         | 
| 60 | 
            +
                      # @example Is the document destroyable?
         | 
| 61 | 
            +
                      #   destroyable?({ :_destroy => "1" })
         | 
| 75 62 | 
             
                      #
         | 
| 76 | 
            -
                      #  | 
| 63 | 
            +
                      # @parma [ Hash ] attributes The attributes to pull the flag from.
         | 
| 77 64 | 
             
                      #
         | 
| 78 | 
            -
                      #  | 
| 65 | 
            +
                      # @return [ true, false ] If the relation can potentially be deleted.
         | 
| 79 66 | 
             
                      def destroyable?(attributes)
         | 
| 80 67 | 
             
                        destroy = attributes.delete(:_destroy)
         | 
| 81 68 | 
             
                        [ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
         | 
| @@ -84,17 +71,12 @@ module Mongoid # :nodoc: | |
| 84 71 | 
             
                      # Are the supplied attributes of greater number than the supplied
         | 
| 85 72 | 
             
                      # limit?
         | 
| 86 73 | 
             
                      #
         | 
| 87 | 
            -
                      #  | 
| 74 | 
            +
                      # @example Are we over the set limit?
         | 
| 75 | 
            +
                      #   builder.over_limit?({ "street" => "Bond" })
         | 
| 88 76 | 
             
                      #
         | 
| 89 | 
            -
                      #  | 
| 77 | 
            +
                      # @param [ Hash ] attributes The attributes being set.
         | 
| 90 78 | 
             
                      #
         | 
| 91 | 
            -
                      #  | 
| 92 | 
            -
                      #
         | 
| 93 | 
            -
                      # attributes: The attributes being set.
         | 
| 94 | 
            -
                      #
         | 
| 95 | 
            -
                      # Returns:
         | 
| 96 | 
            -
                      #
         | 
| 97 | 
            -
                      # True if a limit supplied and the attributes are of greater number.
         | 
| 79 | 
            +
                      # @return [ true, false ] If the attributes exceed the limit.
         | 
| 98 80 | 
             
                      def over_limit?(attributes)
         | 
| 99 81 | 
             
                        limit = options[:limit]
         | 
| 100 82 | 
             
                        limit ? attributes.size > limit : false
         | 
| @@ -103,20 +85,21 @@ module Mongoid # :nodoc: | |
| 103 85 | 
             
                      # Process each set of attributes one at a time for each potential
         | 
| 104 86 | 
             
                      # new, existing, or ignored document.
         | 
| 105 87 | 
             
                      #
         | 
| 106 | 
            -
                      #  | 
| 107 | 
            -
                      #
         | 
| 108 | 
            -
                      # <tt>builder.process({ "id" => 1, "street" => "Bond" })
         | 
| 88 | 
            +
                      # @example Process the attributes
         | 
| 89 | 
            +
                      #   builder.process({ "id" => 1, "street" => "Bond" })
         | 
| 109 90 | 
             
                      #
         | 
| 110 | 
            -
                      #  | 
| 111 | 
            -
                      #
         | 
| 112 | 
            -
                      # attrs: The single document attributes to process.
         | 
| 91 | 
            +
                      # @param [ Hash ] attrs The single document attributes to process.
         | 
| 113 92 | 
             
                      def process(attrs)
         | 
| 114 93 | 
             
                        return if reject?(attrs)
         | 
| 115 94 | 
             
                        if id = attrs["id"] || attrs["_id"]
         | 
| 116 | 
            -
                           | 
| 117 | 
            -
                          destroyable?(attrs) | 
| 95 | 
            +
                          doc = existing.find(convert_id(id))
         | 
| 96 | 
            +
                          if destroyable?(attrs)
         | 
| 97 | 
            +
                            existing.delete(doc)
         | 
| 98 | 
            +
                          else
         | 
| 99 | 
            +
                            metadata.embedded? ? doc.attributes = attrs : doc.update_attributes(attrs)
         | 
| 100 | 
            +
                          end
         | 
| 118 101 | 
             
                        else
         | 
| 119 | 
            -
                          existing.push( | 
| 102 | 
            +
                          existing.push(Factory.build(metadata.klass, attrs)) unless destroyable?(attrs)
         | 
| 120 103 | 
             
                        end
         | 
| 121 104 | 
             
                      end
         | 
| 122 105 | 
             
                    end
         | 
| @@ -17,7 +17,8 @@ module Mongoid # :nodoc: | |
| 17 17 | 
             
                      def build(type = nil)
         | 
| 18 18 | 
             
                        return object unless query?
         | 
| 19 19 | 
             
                        return [] if object.is_a?(Array)
         | 
| 20 | 
            -
                        metadata.criteria(convertable(metadata, object))
         | 
| 20 | 
            +
                        crit = metadata.criteria(convertable(metadata, object))
         | 
| 21 | 
            +
                        IdentityMap.get(crit.klass, crit.selector) || crit
         | 
| 21 22 | 
             
                      end
         | 
| 22 23 |  | 
| 23 24 | 
             
                      private
         | 
| @@ -17,7 +17,7 @@ module Mongoid # :nodoc: | |
| 17 17 | 
             
                      def build(type = nil)
         | 
| 18 18 | 
             
                        return object unless query?
         | 
| 19 19 | 
             
                        criteria = metadata.criteria(object)
         | 
| 20 | 
            -
                        IdentityMap. | 
| 20 | 
            +
                        IdentityMap.get(criteria.klass, criteria.selector) || criteria.first
         | 
| 21 21 | 
             
                      end
         | 
| 22 22 | 
             
                    end
         | 
| 23 23 | 
             
                  end
         | 
| @@ -15,7 +15,6 @@ module Mongoid # :nodoc: | |
| 15 15 | 
             
                  included do
         | 
| 16 16 | 
             
                    class_attribute :cascades
         | 
| 17 17 | 
             
                    self.cascades = []
         | 
| 18 | 
            -
                    delegate :cascades, :to => "self.class"
         | 
| 19 18 | 
             
                  end
         | 
| 20 19 |  | 
| 21 20 | 
             
                  # Perform all cascading deletes, destroys, or nullifies. Will delegate to
         | 
| @@ -33,6 +32,18 @@ module Mongoid # :nodoc: | |
| 33 32 | 
             
                    end
         | 
| 34 33 | 
             
                  end
         | 
| 35 34 |  | 
| 35 | 
            +
                  # Get the cascading definitions.
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # @note Refactored from using delegate for class load performance.
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # @example Get the cascades.
         | 
| 40 | 
            +
                  #   model.cascades
         | 
| 41 | 
            +
                  #
         | 
| 42 | 
            +
                  # @return [ Array<String> ] The cascading relation names.
         | 
| 43 | 
            +
                  def cascades
         | 
| 44 | 
            +
                    self.class.cascades
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 36 47 | 
             
                  module ClassMethods #:nodoc:
         | 
| 37 48 |  | 
| 38 49 | 
             
                    # Attempt to add the cascading information for the document to know how
         | 
| @@ -26,7 +26,7 @@ module Mongoid # :nodoc: | |
| 26 26 | 
             
                        args.flatten.each do |doc|
         | 
| 27 27 | 
             
                          next unless doc
         | 
| 28 28 | 
             
                          append(doc)
         | 
| 29 | 
            -
                          doc.save if persistable?
         | 
| 29 | 
            +
                          doc.save if persistable? && !assigning?
         | 
| 30 30 | 
             
                        end
         | 
| 31 31 | 
             
                      end
         | 
| 32 32 | 
             
                    end
         | 
| @@ -124,7 +124,11 @@ module Mongoid # :nodoc: | |
| 124 124 | 
             
                    def delete(document)
         | 
| 125 125 | 
             
                      target.delete_one(document).tap do |doc|
         | 
| 126 126 | 
             
                        if doc && !binding?
         | 
| 127 | 
            -
                           | 
| 127 | 
            +
                          if assigning?
         | 
| 128 | 
            +
                            base.add_atomic_pull(doc)
         | 
| 129 | 
            +
                          else
         | 
| 130 | 
            +
                            doc.delete(:suppress => true)
         | 
| 131 | 
            +
                          end
         | 
| 128 132 | 
             
                          unbind_one(doc)
         | 
| 129 133 | 
             
                        end
         | 
| 130 134 | 
             
                        reindex
         | 
| @@ -228,6 +232,9 @@ module Mongoid # :nodoc: | |
| 228 232 | 
             
                    def substitute(replacement)
         | 
| 229 233 | 
             
                      tap do |proxy|
         | 
| 230 234 | 
             
                        if replacement.blank?
         | 
| 235 | 
            +
                          if assigning?
         | 
| 236 | 
            +
                            base.atomic_unsets.push(proxy.first.atomic_path)
         | 
| 237 | 
            +
                          end
         | 
| 231 238 | 
             
                          proxy.clear
         | 
| 232 239 | 
             
                        else
         | 
| 233 240 | 
             
                          atomically(:$set) do
         | 
| @@ -238,7 +245,7 @@ module Mongoid # :nodoc: | |
| 238 245 | 
             
                            proxy.target.each_with_index do |doc, index|
         | 
| 239 246 | 
             
                              integrate(doc)
         | 
| 240 247 | 
             
                              doc._index = index
         | 
| 241 | 
            -
                              doc.save if base.persisted?
         | 
| 248 | 
            +
                              doc.save if base.persisted? && !assigning?
         | 
| 242 249 | 
             
                            end
         | 
| 243 250 | 
             
                          end
         | 
| 244 251 | 
             
                        end
         | 
| @@ -377,7 +384,7 @@ module Mongoid # :nodoc: | |
| 377 384 | 
             
                      criteria.size.tap do
         | 
| 378 385 | 
             
                        criteria.each do |doc|
         | 
| 379 386 | 
             
                          target.delete_one(doc)
         | 
| 380 | 
            -
                          doc.send(method, :suppress => true)
         | 
| 387 | 
            +
                          doc.send(method, :suppress => true) unless assigning?
         | 
| 381 388 | 
             
                          unbind_one(doc)
         | 
| 382 389 | 
             
                        end
         | 
| 383 390 | 
             
                        reindex
         | 
| @@ -36,7 +36,11 @@ module Mongoid # :nodoc: | |
| 36 36 | 
             
                    # @since 2.0.0.rc.1
         | 
| 37 37 | 
             
                    def substitute(replacement)
         | 
| 38 38 | 
             
                      tap do |proxy|
         | 
| 39 | 
            -
                         | 
| 39 | 
            +
                        if assigning?
         | 
| 40 | 
            +
                          base.atomic_unsets.push(proxy.atomic_path)
         | 
| 41 | 
            +
                        else
         | 
| 42 | 
            +
                          proxy.delete
         | 
| 43 | 
            +
                        end
         | 
| 40 44 | 
             
                        proxy.unbind_one
         | 
| 41 45 | 
             
                        return nil unless replacement
         | 
| 42 46 | 
             
                        proxy.target = replacement
         | 
| @@ -69,7 +73,7 @@ module Mongoid # :nodoc: | |
| 69 73 | 
             
                    #
         | 
| 70 74 | 
             
                    # @since 2.1.0
         | 
| 71 75 | 
             
                    def persistable?
         | 
| 72 | 
            -
                      base.persisted? && !binding? && !building?
         | 
| 76 | 
            +
                      base.persisted? && !binding? && !building? && !assigning?
         | 
| 73 77 | 
             
                    end
         | 
| 74 78 |  | 
| 75 79 | 
             
                    class << self
         | 
| @@ -7,10 +7,6 @@ module Mongoid # :nodoc: | |
| 7 7 | 
             
                module Macros
         | 
| 8 8 | 
             
                  extend ActiveSupport::Concern
         | 
| 9 9 |  | 
| 10 | 
            -
                  # Convenience methods for the instance to know about attributes that
         | 
| 11 | 
            -
                  # are located at the class level.
         | 
| 12 | 
            -
                  delegate :associations, :relations, :to => "self.class"
         | 
| 13 | 
            -
             | 
| 14 10 | 
             
                  included do
         | 
| 15 11 | 
             
                    cattr_accessor :embedded
         | 
| 16 12 | 
             
                    class_attribute :relations
         | 
| @@ -27,6 +23,19 @@ module Mongoid # :nodoc: | |
| 27 23 | 
             
                    end
         | 
| 28 24 | 
             
                  end
         | 
| 29 25 |  | 
| 26 | 
            +
                  # Get the metadata for all the defined relations.
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  # @note Refactored from using delegate for class load performance.
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # @example Get the relations.
         | 
| 31 | 
            +
                  #   model.relations
         | 
| 32 | 
            +
                  #
         | 
| 33 | 
            +
                  # @return [ Hash<String, Metadata> ] The relation metadata.
         | 
| 34 | 
            +
                  def relations
         | 
| 35 | 
            +
                    self.class.relations
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                  alias :associations :relations
         | 
| 38 | 
            +
             | 
| 30 39 | 
             
                  module ClassMethods #:nodoc:
         | 
| 31 40 |  | 
| 32 41 | 
             
                    # Adds the relation back to the parent document. This macro is
         | 
| @@ -241,14 +250,12 @@ module Mongoid # :nodoc: | |
| 241 250 | 
             
                    #
         | 
| 242 251 | 
             
                    # @return [ Metadata ] The metadata for the relation.
         | 
| 243 252 | 
             
                    def characterize(name, relation, options, &block)
         | 
| 244 | 
            -
                      Metadata.new(
         | 
| 245 | 
            -
                         | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
                        )
         | 
| 251 | 
            -
                      )
         | 
| 253 | 
            +
                      Metadata.new({
         | 
| 254 | 
            +
                        :relation => relation,
         | 
| 255 | 
            +
                        :extend => create_extension_module(name, &block),
         | 
| 256 | 
            +
                        :inverse_class_name => self.name,
         | 
| 257 | 
            +
                        :name => name
         | 
| 258 | 
            +
                      }.merge(options))
         | 
| 252 259 | 
             
                    end
         | 
| 253 260 |  | 
| 254 261 | 
             
                    # Generate a named extension module suitable for marshaling
         |