class ActiveRecord::Base
Public Class Methods
allow_dup()
click to toggle source
# File lib/clone_util.rb, line 8 def self.allow_dup @clone_options[:allow_dup] end
clone_associations()
click to toggle source
# File lib/clone_util.rb, line 16 def self.clone_associations @clone_options[:associations] end
clone_info()
click to toggle source
# File lib/clone_util.rb, line 12 def self.clone_info @clone_options end
deep_clone_options(options={})
click to toggle source
# File lib/clone_util.rb, line 3 def self.deep_clone_options(options={}) class_eval do @clone_options = options def self.allow_dup @clone_options[:allow_dup] end def self.clone_info @clone_options end def self.clone_associations @clone_options[:associations] end def self.equivalent_associations @clone_options[:equivalent_associations] end def self.unequal_attrs unequal_attrs = ['id'] unequal_attrs.concat(@clone_options[:unequal_attributes]) if @clone_options[:unequal_attributes] unequal_attrs end def self.ignore_attributes ignore_attributes = ['created_at', 'updated_at', 'created_by_id', 'updated_by_id'] ignore_attributes << @clone_options[:parent_id_attr].first if @clone_options[:parent_id_attr] ignore_attributes end def self.parent_id_attr @clone_options[:parent_id_attr] end def deep_clone recursive_clone end #TODO Should be private/protected def recursive_clone(parent_object_id = nil, clone_id_hash = {} ) self.transaction do cloned_object = dup unequal_attrs = self.class.clone_info[:unequal_attributes] || [] unequal_attrs.each do |a| cloned_object.send("#{a.to_s}=", nil) end #Set parent object_id if self.class.parent_id_attr and parent_object_id cloned_object.send("#{self.class.parent_id_attr[0].to_s}=", parent_object_id) end begin obj_attrs = cloned_object.attributes.clone self.class.ignore_attributes.each { |a| obj_attrs.delete(a.to_s)} if self.class.parent_id_attr and parent_object_id obj_attrs["#{self.class.parent_id_attr[0].to_s}"] = parent_object_id end cloned_object.save! clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id rescue Exception => e logger.info("deepclone: Clone save failed for " + cloned_object.inspect) raise e end add_cloned_associations(cloned_object, clone_id_hash) add_equivalent_associations(cloned_object, clone_id_hash) clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id cloned_object end # transaction end # recursive_clone def add_equivalent_associations(cloned_object, clone_id_hash) if self.class.equivalent_associations self.class.equivalent_associations.each do |association| assocn = self.class.reflect_on_association(association) assocn_table_name = eval(assocn.class_name).table_name assocn_id = send(assocn.foreign_key) if assocn_id and (equivalent_id = clone_id_hash["#{assocn_table_name}_#{assocn_id}"]) cloned_object.send("#{assocn.foreign_key}=", equivalent_id) end end cloned_object.save! end end def add_cloned_associations(cloned_object, clone_id_hash) if self.class.clone_associations self.class.clone_associations.each do |association| assocn = self.class.reflect_on_association(association) if assocn.macro == :has_many send(association).each do |obj| c_obj = obj.respond_to?('deep_clone') ? obj.recursive_clone(cloned_object.id, clone_id_hash) : obj.dup cloned_object.send(association) << c_obj unless c_obj.nil? end elsif assocn.macro == :has_and_belongs_to_many cloned_object.send("#{association.to_s}=", send(association)) elsif (assocn.macro == :belongs_to) or (assocn.macro == :has_one) source_obj = send(association) unless source_obj.nil? c_obj = source_obj.respond_to?('deep_clone') ? source_obj.recursive_clone(cloned_object.id, clone_id_hash) : source_obj.dup cloned_object.send("#{association.to_s}=", c_obj) unless c_obj.nil? end end end end end end # class_eval end
equivalent_associations()
click to toggle source
# File lib/clone_util.rb, line 20 def self.equivalent_associations @clone_options[:equivalent_associations] end
ignore_attributes()
click to toggle source
# File lib/clone_util.rb, line 30 def self.ignore_attributes ignore_attributes = ['created_at', 'updated_at', 'created_by_id', 'updated_by_id'] ignore_attributes << @clone_options[:parent_id_attr].first if @clone_options[:parent_id_attr] ignore_attributes end
parent_id_attr()
click to toggle source
# File lib/clone_util.rb, line 36 def self.parent_id_attr @clone_options[:parent_id_attr] end
unequal_attrs()
click to toggle source
# File lib/clone_util.rb, line 24 def self.unequal_attrs unequal_attrs = ['id'] unequal_attrs.concat(@clone_options[:unequal_attributes]) if @clone_options[:unequal_attributes] unequal_attrs end
Public Instance Methods
add_cloned_associations(cloned_object, clone_id_hash)
click to toggle source
# File lib/clone_util.rb, line 97 def add_cloned_associations(cloned_object, clone_id_hash) if self.class.clone_associations self.class.clone_associations.each do |association| assocn = self.class.reflect_on_association(association) if assocn.macro == :has_many send(association).each do |obj| c_obj = obj.respond_to?('deep_clone') ? obj.recursive_clone(cloned_object.id, clone_id_hash) : obj.dup cloned_object.send(association) << c_obj unless c_obj.nil? end elsif assocn.macro == :has_and_belongs_to_many cloned_object.send("#{association.to_s}=", send(association)) elsif (assocn.macro == :belongs_to) or (assocn.macro == :has_one) source_obj = send(association) unless source_obj.nil? c_obj = source_obj.respond_to?('deep_clone') ? source_obj.recursive_clone(cloned_object.id, clone_id_hash) : source_obj.dup cloned_object.send("#{association.to_s}=", c_obj) unless c_obj.nil? end end end end end
add_equivalent_associations(cloned_object, clone_id_hash)
click to toggle source
# File lib/clone_util.rb, line 83 def add_equivalent_associations(cloned_object, clone_id_hash) if self.class.equivalent_associations self.class.equivalent_associations.each do |association| assocn = self.class.reflect_on_association(association) assocn_table_name = eval(assocn.class_name).table_name assocn_id = send(assocn.foreign_key) if assocn_id and (equivalent_id = clone_id_hash["#{assocn_table_name}_#{assocn_id}"]) cloned_object.send("#{assocn.foreign_key}=", equivalent_id) end end cloned_object.save! end end
deep_clone()
click to toggle source
# File lib/clone_util.rb, line 40 def deep_clone recursive_clone end
recursive_clone(parent_object_id = nil, clone_id_hash = {} )
click to toggle source
TODO Should be private/protected
# File lib/clone_util.rb, line 45 def recursive_clone(parent_object_id = nil, clone_id_hash = {} ) self.transaction do cloned_object = dup unequal_attrs = self.class.clone_info[:unequal_attributes] || [] unequal_attrs.each do |a| cloned_object.send("#{a.to_s}=", nil) end #Set parent object_id if self.class.parent_id_attr and parent_object_id cloned_object.send("#{self.class.parent_id_attr[0].to_s}=", parent_object_id) end begin obj_attrs = cloned_object.attributes.clone self.class.ignore_attributes.each { |a| obj_attrs.delete(a.to_s)} if self.class.parent_id_attr and parent_object_id obj_attrs["#{self.class.parent_id_attr[0].to_s}"] = parent_object_id end cloned_object.save! clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id rescue Exception => e logger.info("deepclone: Clone save failed for " + cloned_object.inspect) raise e end add_cloned_associations(cloned_object, clone_id_hash) add_equivalent_associations(cloned_object, clone_id_hash) clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id cloned_object end # transaction end