Class: DataShift::Populators::HasMany

Inherits:
Object
  • Object
show all
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

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 = Querying.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