lib/loaders/loader_base.rb in datashift-0.0.2 vs lib/loaders/loader_base.rb in datashift-0.1.0

- old
+ new

@@ -79,22 +79,27 @@ def self.multi_assoc_delim @multi_assoc_delim ||= '|' @multi_assoc_delim end - + def self.set_multi_assoc_delim(x) @multi_assoc_delim = x; end + # Options # :instance_methods => true def initialize(object_class, object = nil, options = {}) @load_object_class = object_class - # Gather list of all possible 'setter' methods on AR class (instance variables and associations) - DataShift::MethodMapper.find_operators( @load_object_class, :reload => true, :instance_methods => options[:instance_methods] ) + # Gather names of all possible 'setter' methods on AR class (instance variables and associations) + DataShift::MethodDictionary.find_operators( @load_object_class, :reload => true, :instance_methods => options[:instance_methods] ) + # Create dictionary of data on all possible 'setter' methods which can be used to + # populate or integrate an object of type @load_object_class + DataShift::MethodDictionary.build_method_details(@load_object_class) + @method_mapper = DataShift::MethodMapper.new @options = options.clone @headers = [] @default_data_objects ||= {} @@ -113,19 +118,22 @@ def perform_load( input, options = {} ) raise "WARNING- ABSTRACT METHOD CALLED - Please implement perform_load()" end - # Core API - Given a list of free text column names from a file, map all headers to - # method mapper's operator list. + # Core API - Given a list of free text column names from a file, + # map all headers to a method detail containing operator details. + # + # This is then available through @method_mapper.method_details.each + # # Options: # strict : report any header values that can't be mapped as an error # def map_headers_to_operators( headers, strict, mandatory = []) @headers = headers - @method_mapper.populate_methods( load_object_class, @headers ) + method_details = @method_mapper.map_inbound_to_methods( load_object_class, @headers ) unless(@method_mapper.missing_methods.empty?) puts "WARNING: Following column headings could not be mapped : #{@method_mapper.missing_methods.inspect}" raise MappingDefinitionError, "Missing mappings for columns : #{@method_mapper.missing_methods.join(",")}" if(strict) end @@ -135,16 +143,16 @@ raise MissingMandatoryError, "Mandatory columns missing - please fix and retry." end unless(mandatory.empty?) end - # Core API - Given a free text column name from a file, search method mapper for + # Core API - Given a single free text column name from a file, search method mapper for # associated operator on base object class. # # If suitable association found, process row data and then assign to current load_object def find_and_process(column_name, data) - method_detail = MethodMapper.find_method_detail( load_object_class, column_name ) + method_detail = MethodDictionary.find_method_detail( load_object_class, column_name ) if(method_detail) prepare_data(method_detail, data) process() else @@ -240,36 +248,45 @@ # has_and_belongs_to associations which require the load_object has an id for the join table save_if_new # A single column can contain multiple associations delimited by special char + # Size:large|Colour:red,green,blue => ['Size:large', 'Colour:red,green,blue'] columns = @current_value.to_s.split( LoaderBase::multi_assoc_delim) # Size:large|Colour:red,green,blue => generates find_by_size( 'large' ) and find_all_by_colour( ['red','green','blue'] ) - columns.each do |assoc| - operator, values = assoc.split(LoaderBase::name_value_delim) + columns.each do |col_str| + + find_operator, col_values = "","" + + if(@current_method_detail.find_by_operator) + find_operator, col_values = @current_method_detail.find_by_operator, col_str + else + find_operator, col_values = col_str.split(LoaderBase::name_value_delim) + raise "No key to find #{@current_method_detail.operator} in DB. Expected format key:value" unless(col_values) + end + + find_by_values = col_values.split(LoaderBase::multi_value_delim) - lookups = values.split(LoaderBase::multi_value_delim) + if(find_by_values.size > 1) - if(lookups.size > 1) + @current_value = @current_method_detail.operator_class.send("find_all_by_#{find_operator}", find_by_values ) - @current_value = @current_method_detail.operator_class.send("find_all_by_#{operator}", lookups ) - - unless(lookups.size == @current_value.size) - found = @current_value.collect {|f| f.send(operator) } - @load_object.errors.add( method_detail.operator, "Association with key(s) #{(lookups - found).inspect} NOT found") + unless(find_by_values.size == @current_value.size) + found = @current_value.collect {|f| f.send(find_operator) } + @load_object.errors.add( @current_method_detail.operator, "Association with key(s) #{(find_by_values - found).inspect} NOT found") puts "WARNING: Association with key(s) #{(lookups - found).inspect} NOT found - Not added." next if(@current_value.empty?) end else - @current_value = @current_method_detail.operator_class.send("find_by_#{operator}", lookups ) + @current_value = @current_method_detail.operator_class.send("find_by_#{find_operator}", find_by_values ) unless(@current_value) - @load_object.errors.add( @current_method_detail.operator, "Association with key #{lookups} NOT found") - puts "WARNING: Association with key #{lookups} NOT found - Not added." + @load_object.errors.add( @current_method_detail.operator, "Association with key #{find_by_values} NOT found") + puts "WARNING: Association with key #{find_by_values} NOT found - Not added." next end end \ No newline at end of file