module ActiveRecord::Cloneable::InstanceMethods
Public Instance Methods
clone_basic_details(cloned_record, belongs_to_keys, args )
click to toggle source
—————————————————— clone_basic_details
# File lib/active_record/cloneable.rb, line 17 def clone_basic_details(cloned_record, belongs_to_keys, args ) # assign the attributes, minus any assigned or any from a belongs_to relation self.class.content_columns.each do |column| if !args[:attributes].has_key?( column.name.to_sym ) && !belongs_to_keys.include?( column.name.to_sym ) m = "#{column.name}=".to_sym if cloned_record.respond_to?( m ) cloned_record.send( m, read_attribute( column.name ) ) else cloned_record.write_attribute( column.name, read_attribute( column.name ) ) end end end args[:attributes].each_pair do |k,v| cloned_record.send( "#{k}=", v ) end # Set the name or title field to be the existing value + (copy) ( args[:name_fields] || [:name,:title] ).each do |name_attr| if has_attribute?( name_attr ) && read_attribute( :name_attr ) cloned_form.write_attribute( name_attr, read_attribute( name_attr ) + ' (copy)' ) break if args[:name_fields].nil? end end #cloned_record.save end
clone_belongs_to_relations( relations, cloned_record, args )
click to toggle source
———————————————– clone_bleongs_to_relations
# File lib/active_record/cloneable.rb, line 42 def clone_belongs_to_relations( relations, cloned_record, args ) return if relations.nil? relations.each do |parent_relation| obj = send( parent_relation.name ) next if obj.nil? next if args[:skipped_children].include?( obj ) args[:skipped_children] += [ obj ] if args[:shared_parent_relations].include?( parent_relation.name.to_sym ) cloned_record.send( "#{parent_relation.name}=", obj ) elsif !args[:cloned_parents].include?( obj ) # We don't know what the parent calls this child. begin rec = obj.clone_record( skipped_children: args[:skipped_children], cloned_parents: args[:cloned_parents] + [self], stack: args[:stack] + [ parent_relation.name ], skipped_child_relations: find_applicable_clone_args( parent_relation.name, args[:skipped_child_relations] ), skipped_parent_relations: find_applicable_clone_args( parent_relation.name, args[:skipped_parent_relations] ), shared_parent_relations: find_applicable_clone_args( parent_relation.name, args[:shared_parent_relations] ) ) rescue NoMethodError => ex handle_cloneable_exception(ex, "#{obj.class.name} objects do not know how to clone themselves; they should be marked as cloneable or skipped.") end cloned_record.send( "#{parent_relation.name}=", rec ) end end end
clone_child_relation?( relation_name, skipped_child_relations )
click to toggle source
—————————————————- clone_child_relation?
# File lib/active_record/cloneable.rb, line 82 def clone_child_relation?( relation_name, skipped_child_relations ) relation_name = relation_name.to_sym skipped_child_relations.each do |relation| unless relation.is_a?( Hash ) return false if relation == relation_name end end return true end
clone_record( args = {} )
click to toggle source
———————————————————————- clone
# File lib/active_record/cloneable.rb, line 92 def clone_record( args = {} ) args[:shared_parent_relations] ||= [] args[:skipped_child_relations] ||= [] args[:cloned_parents] ||= [] args[:skipped_children] ||= [self] args[:attributes] ||={} args[:stack] ||= [] cloned_record = args[:object] || self.class.new data = {} self.class.reflections.each do |k,v| data[v.macro] ||= [] data[v.macro] << v end belongs_to_keys = ( data[:belongs_to] || [] ).map{ |x| x.association_primary_key } clone_belongs_to_relations( data[:belongs_to], cloned_record, args ) clone_basic_details( cloned_record, belongs_to_keys, args ) ((data[:has_many] || []) + (data[:has_and_belongs_to_many]||[]) ).each do |child_relation| next if child_relation.through_reflection next if !clone_child_relation?( child_relation.name, args[:skipped_child_relations] ) kids = send( child_relation.name ).to_a next if kids.nil? kids.each do |child_record| next if args[:skipped_children].include?( child_record ) args[:skipped_children] += [child_record] cloned_child_record = send( child_relation.name ).build child_args = { cloned_parents: args[:cloned_parents] + [self], attributes: {}, stack: args[:stack] + [ child_relation.name ], object: cloned_child_record, skipped_children: args[:skipped_children], skipped_parent_relations: find_applicable_clone_args( child_relation.name, args[:skipped_parent_relations] ), shared_parent_relations: find_applicable_clone_args( child_relation.name, args[:shared_parent_relations] ), skipped_child_relations: find_applicable_clone_args( child_relation.name, args[:skipped_child_relations] ) } #if child_relation.macro == :has_many ||child_relation.macro == :has_one # child_args[:attributes][child_relation.primary_key_name.to_sym] = nil #end begin cloned_child_record = child_record.clone_record( child_args ) cloned_record.send( child_relation.name ) << cloned_child_record rescue NoMethodError => ex handle_cloneable_exception(ex, "#{child_record.class.name} objects do not know how to clone themselves; they should be marked as cloneable or skipped. (#{self.class.name} / #{child_relation.name}") end end end ( data[:has_one] || []).each do |child_relation| next if child_relation.through_reflection next if !clone_child_relation?( child_relation.name, args[:skipped_child_relations] ) kid = send( child_relation.name ) next if kid.nil? next if args[:skipped_children].include?( kid ) args[:skipped_children] += [kid] cloned_child_record = kid.build child_args = { cloned_parents: args[:cloned_parents] + [self], attributes: {}, object: cloned_child_record, skipped_children: args[:skipped_children], stack: args[:stack] + [ child_relation.name ] , skipped_child_relations: args[:skipped_child_relations].find_all{ |x| x.is_a?( Hash ) && x[child_relation.name.to_sym] }.map{ |x| x.values }.flatten } begin cloned_child_record = kid.clone_record( child_args ) cloned_record.send( "#{child_relation.name}=", cloned_child_record ) rescue NoMethodError => ex handle_cloneable_exception(ex, "#{kid.class.name} objects do not know how to clone themselves; they should be marked as cloneable or skipped. (#{self.class.name} / #{child_relation.name} -- #{args[:stack].inspect}") end end return cloned_record end
find_applicable_clone_args( relation_name, args )
click to toggle source
———————————————– find_applicable_clone_args
# File lib/active_record/cloneable.rb, line 69 def find_applicable_clone_args( relation_name, args ) relation_name = relation_name.to_sym return nil if args.nil? r_val = args.map do |x| if x.is_a?( Hash ) x[relation_name] else nil end end r_val.flatten.compact end
handle_cloneable_exception(ex, msg)
click to toggle source
# File lib/active_record/cloneable.rb, line 162 def handle_cloneable_exception(ex, msg) if ex.name.to_sym == :clone_record raise msg else raise ex end end