123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Copyable

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ActiveSupport::Concern
Defined in: lib/mongoid/copyable.rb

Overview

This module contains the behavior of Mongoid’s clone/dup of documents.

Class Method Summary

Instance Method Summary

Class Method Details

.clone_with_hash(klass, attrs) ⇒ Document (private)

Create clone of a document of the given klass with the given attributes hash. This is used recursively so that embedded associations are cloned safely.

Parameters:

  • klass (Class)

    The class of the document to create.

  • attrs (Hash)

    The hash of the attributes.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/copyable.rb', line 44

def self.clone_with_hash(klass, attrs)
  dynamic_attrs = {}
  _attribute_names = klass.attribute_names
  attrs.reject! do |attr_name, value|
    unless _attribute_names.include?(attr_name)
      dynamic_attrs[attr_name] = value
      true
    end
  end

  Factory.build(klass, attrs).tap do |object|
    dynamic_attrs.each do |attr_name, value|
      assoc = object.embedded_relations[attr_name]
      if assoc&.one? && Hash === value
        object.send("#{attr_name}=", clone_with_hash(assoc.klass, value))
      elsif assoc&.many? && Array === value
        docs = value.map { |h| clone_with_hash(assoc.klass, h) }
        object.send("#{attr_name}=", docs)
      elsif object.respond_to?("#{attr_name}=")
        object.send("#{attr_name}=", value)
      else
        object.attributes[attr_name] = value
      end
    end
  end
end

Instance Method Details

#cloneDocument Also known as: #dup

Clone or dup the current Document. This will return all attributes with the exception of the document’s id, and will reset all the instance variables.

This clone also includes embedded documents. If there is an _id field in the embedded document, it will be maintained, unlike the root’s _id.

If cloning an embedded child, the embedded parent is not cloned and the embedded_in association is not set.

Examples:

Clone the document.

document.clone

Returns:

[ GitHub ]

  
# File 'lib/mongoid/copyable.rb', line 24

def clone
  # @note This next line is here to address #2704, even though having an
  # _id and id field in the document would cause problems with Mongoid
  # elsewhere. Note this is only done on the root document as we want
  # to maintain the same _id on the embedded documents.
  attrs = clone_document.except(*self.class.id_fields)
  Copyable.clone_with_hash(self.class, attrs)
end

#clone_document (private)

This method is for internal use only.

Clone the document attributes

Examples:

clone document

model.clone_document
[ GitHub ]

  
# File 'lib/mongoid/copyable.rb', line 77

def clone_document
  attrs = as_attributes.__deep_copy__
  process_localized_attributes(self, attrs)
  attrs
end

#dup

Alias for #clone.

[ GitHub ]

  
# File 'lib/mongoid/copyable.rb', line 32

alias :dup :clone

#process_localized_attributes(klass, attrs) (private)

This method is for internal use only.

When cloning, if the document has localized fields we need to ensure they are properly processed in the clone.

Examples:

Process localized attributes.

model.process_localized_attributes(attributes)

Parameters:

  • attrs (Hash)

    The attributes.

[ GitHub ]

  
# File 'lib/mongoid/copyable.rb', line 92

def process_localized_attributes(klass, attrs)
  klass.localized_fields.keys.each do |name|
    if value = attrs.delete(name)
      attrs["#{name}_translations"] = value
    end
  end
  klass.embedded_relations.each do |_, association|
    next unless attrs.present? && attrs[association.key].present?

    if association.is_a?(Association::Embedded::EmbedsMany)
      attrs[association.key].each do |attr|
        embedded_klass = if type = attr[self.class.discriminator_key]
          association.relation_class.get_discriminator_mapping(type) || association.relation_class
        else
          association.relation_class
        end
        process_localized_attributes(embedded_klass, attr)
      end
    else
      process_localized_attributes(association.klass, attrs[association.key])
    end
  end
end