Module: Iqvoc::DeepCloning

Defined in:
lib/iqvoc/deep_cloning.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

:nodoc:



19
20
21
# File 'lib/iqvoc/deep_cloning.rb', line 19

def self.included(base) #:nodoc:
  base.alias_method_chain :dup, :deep_cloning
end

Instance Method Details

#dup_with_deep_cloning(options = {}) ⇒ Object

clones an ActiveRecord model. if passed the :include option, it will deep clone the given associations if passed the :except option, it won’t clone the given attributes

Usage:

Cloning a model without an attribute

pirate.clone except: :name

Cloning a model without multiple attributes

pirate.clone except: [:name, :nick_name]

Cloning one single association

pirate.clone include: :mateys

Cloning multiple associations

pirate.clone include: [:mateys, :treasures]

Cloning really deep

pirate.clone include: :gold_pieces

Cloning really deep with multiple associations

pirate.clone include: [:mateys, :gold_pieces]

Cloning multiple associations - but only the join table entries without cloning the associated objects themselves

pirate.clone include_association: [:matey_ids, :treasure_ids]



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/iqvoc/deep_cloning.rb', line 49

def dup_with_deep_cloning(options = {})
  kopy = dup_without_deep_cloning

  if options[:except]
    Array(options[:except]).each do |attribute|
      kopy.write_attribute(attribute, attributes_from_column_definition[attribute.to_s])
    end
  end

  if options[:include_association]
    Array(options[:include_association]).each do |association_attribute|
      kopy.send("#{association_attribute}=", self.send("#{association_attribute}"))
    end
  end

  if options[:include]
    Array(options[:include]).each do |association, deep_associations|
      if (association.kind_of? Hash)
        deep_associations = association[association.keys.first]
        association = association.keys.first
      end
      opts = deep_associations.blank? ? {} : { include: deep_associations }
      association_reflection = self.class.reflect_on_association(association)
      cloned_object = case association_reflection.macro
      when :belongs_to, :has_one
        self.send(association) && self.send(association).dup(opts)
      when :has_many, :has_and_belongs_to_many
        fk = association_reflection.options[:foreign_key]# || self.class.to_s.underscore
        self.send(association).collect do |obj|
          cloned_obj = obj.dup(opts)
          cloned_obj.send("#{fk}=", kopy.id) unless fk.blank?
          cloned_obj
        end
      end
      kopy.send("#{association}=", cloned_object)
    end
  end

  return kopy
end