ActiveRecord::Base::DeepCloneable

Public Instance Methods

deep_clone(*args, &block) click to toggle source

Deep dups an ActiveRecord model. See README.rdoc

# File lib/deep_cloneable.rb, line 5
def deep_clone *args, &block
  options = args[0] || {}

  dict = options[:dictionary]
  dict ||= {} if options.delete(:use_dictionary)

  kopy = unless dict
    dup()
  else
    tableized_class = self.class.name.tableize.to_sym
    dict[tableized_class] ||= {}
    dict[tableized_class][self] ||= dup()
  end

  block.call(self, kopy) if block

  deep_exceptions = {}
  if options[:except]
    exceptions = options[:except].nil? ? [] : [options[:except]].flatten
    exceptions.each do |attribute|
      kopy.send(:write_attribute, attribute, self.class.column_defaults.dup[attribute.to_s]) unless attribute.kind_of?(Hash)
    end
    deep_exceptions = exceptions.select{|e| e.kind_of?(Hash) }.inject({}){|m,h| m.merge(h) }
  end

  deep_onlinesses = {}
  if options[:only]
    onlinesses = options[:only].nil? ? [] : [options[:only]].flatten
    object_attrs = kopy.attributes.keys.collect{ |s| s.to_sym }
    exceptions = object_attrs - onlinesses
    exceptions.each do |attribute|
      kopy.send(:write_attribute, attribute, self.class.column_defaults.dup[attribute.to_s]) unless attribute.kind_of?(Hash)
    end
    deep_onlinesses = onlinesses.select{|e| e.kind_of?(Hash) }.inject({}){|m,h| m.merge(h) }
  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

      dup_options = deep_associations.blank? ? {} : {:include => deep_associations}
      dup_options.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
      dup_options.merge!(:only => deep_onlinesses[association]) if deep_onlinesses[association]
      dup_options.merge!(:dictionary => dict) if dict

      association_reflection = self.class.reflect_on_association(association)
      raise AssociationNotFoundException.new("#{self.class}##{association}") if association_reflection.nil?

      if options[:validate] == false
        kopy.instance_eval do
          # Force :validate => false on all saves.
          def perform_validations(options={})
            options[:validate] = false
            super(options)
          end
        end
      end

      cloned_object = send(
        "dup_#{association_reflection.macro}_#{association_reflection.class.name.demodulize.underscore.gsub('_reflection', '')}",
        { :reflection => association_reflection, :association => association, :copy => kopy, :dup_options => dup_options },
        &block
      )

      kopy.send("#{association}=", cloned_object)
    end
  end

  return kopy
end
perform_validations(options={}) click to toggle source

Force :validate => false on all saves.

# File lib/deep_cloneable.rb, line 59
def perform_validations(options={})
  options[:validate] = false
  super(options)
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.