Class: DataShift::Populators::HasMany
- Inherits:
-
Object
- Object
- DataShift::Populators::HasMany
- Extended by:
- Delimiters, Logging
- Includes:
- Delimiters, Logging
- Defined in:
- lib/datashift/populators/has_many.rb
Instance Attribute Summary
Attributes included from Delimiters
#attribute_list_end, #attribute_list_start, #csv_delimiter, #key_value_sep, #text_delim
Class Method Summary collapse
-
.call(load_object, value, method_binding) ⇒ Object
def self.call(record, value, operator).
-
.split_into_multiple_lookup(value) ⇒ Object
A single column can contain multiple lookup key:value definitions.
Methods included from Logging
logdir, logdir=, logger, verbose
Methods included from Delimiters
column_delim, column_delim=, eol, multi_assoc_delim, multi_assoc_delim=, multi_facet_delim, multi_value_delim, multi_value_delim=, name_value_delim, name_value_delim=, setmulti_facet_delim
Class Method Details
.call(load_object, value, method_binding) ⇒ Object
def self.call(record, value, operator)
39 40 41 42 43 44 45 46 47 48 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/datashift/populators/has_many.rb', line 39 def self.call(load_object, value, method_binding) # there are times when we need to save early, for example before assigning to # has_and_belongs_to associations which require the load_object has an id for the join table load_object.save_if_new collection = [] columns = [] if value.is_a?(Array) value.each do |record| if record.class.ancestors.include?(ActiveRecord::Base) collection << record else columns << record end end else columns = split_into_multiple_lookup(value) end operator = method_binding.operator columns.each do |col_str| # split into usable parts ; size:large or colour:red,green,blue field, find_by_values = .where_field_and_values(method_binding, col_str ) raise "Cannot perform DB find by #{field}. Expected format key:value" unless field && find_by_values found_values = [] # we are looking up an association so need the Class of the Association klass = method_binding.model_method.operator_class raise CouldNotDeriveAssociationClass, "Failed to find class for has_many Association : #{method_binding.pp}" unless klass logger.info("Running where clause on #{klass} : [#{field} IN #{find_by_values.inspect}]") find_by_values.each do |v| begin found_values << klass.where(field => v).first_or_create rescue => e logger.error(e.inspect) logger.error("Failed to find or create #{klass} where #{field} => #{v}") # TODO: some way to define if this is a fatal error or not ? end end logger.info("Scan result #{found_values.inspect}") unless find_by_values.size == found_values.size found = found_values.collect { |f| f.send(field) } load_object.errors.add( operator, "Association with key(s) #{(find_by_values - found).inspect} NOT found") logger.error "Association [#{operator}] with key(s) #{(find_by_values - found).inspect} NOT found - Not added." next if found_values.empty? end logger.info("Assigning to has_many [#{operator}] : #{found_values.inspect} (#{found_values.class})") begin load_object.send(operator) << found_values rescue => e logger.error e.inspect logger.error "Cannot assign #{found_values.inspect} to has_many [#{operator}] " end logger.info("Assignment to has_many [#{operator}] COMPLETE)") end end |
.split_into_multiple_lookup(value) ⇒ Object
A single column can contain multiple lookup key:value definitions. These are delimited by special char defined in Delimiters
For example:
size:large | colour:red,green,blue |
Should result in
=> [where size: 'large'], [where colour: IN ['red,green,blue']
33 34 35 |
# File 'lib/datashift/populators/has_many.rb', line 33 def self.split_into_multiple_lookup(value) value.to_s.split( multi_assoc_delim ) end |