Class: CSVImporter::Row

Inherits:
Object
  • Object
show all
Defined in:
lib/csv_importer/row.rb

Overview

A Row from the CSV file.

Using the header, the model_klass and the identifier it builds the model to be persisted.

Instance Method Summary collapse

Instance Method Details

#build_modelObject



109
110
111
# File 'lib/csv_importer/row.rb', line 109

def build_model
  model_klass.new
end

#csv_attributesObject

A hash with this row’s attributes



30
31
32
# File 'lib/csv_importer/row.rb', line 30

def csv_attributes
  @csv_attributes ||= Hash[header.column_names.zip(row_array)]
end

#errorsObject

Error from the model mapped back to the CSV header if we can



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/csv_importer/row.rb', line 78

def errors
  Hash[
    model.errors.to_hash.map do |attribute, errors|
      if column_name = header.column_name_for_model_attribute(attribute)
        [column_name, errors.last]
      else
        [attribute, errors.last]
      end
    end
  ]
end

#find_modelObject



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/csv_importer/row.rb', line 94

def find_model
  return nil if identifiers.nil?

  model = build_model
  set_attributes(model)

  identifiers = model_identifiers(model)
  return nil if identifiers.empty?

  query = Hash[
    identifiers.map { |identifier| [ identifier, model.public_send(identifier) ] }
  ]
  model_klass.find_by(query)
end

#find_or_build_modelObject



90
91
92
# File 'lib/csv_importer/row.rb', line 90

def find_or_build_model
  find_model || build_model
end

#modelObject

The model to be persisted



18
19
20
21
22
23
24
25
26
27
# File 'lib/csv_importer/row.rb', line 18

def model
  @model ||= begin
    model = find_or_build_model

    set_attributes(model)

    after_build_blocks.each { |block| instance_exec(model, &block) }
    model
  end
end

#set_attribute(model, column, csv_value) ⇒ Object

Set the attribute using the column_definition and the csv_value



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/csv_importer/row.rb', line 53

def set_attribute(model, column, csv_value)
  column_definition = column.definition
  transformer = column_definition.to
  if transformer.respond_to?(:call)
    arity = transformer.is_a?(Proc) ? transformer.arity : transformer.method(:call).arity

    case arity
    when 1 # to: ->(email) { email.downcase }
      model.public_send("#{column_definition.name}=", transformer.call(csv_value))
    when 2 # to: ->(published, post) { post.published_at = Time.now if published == "true" }
      transformer.call(csv_value, model)
    when 3 # to: ->(field_value, post, column) { post.hash_field[column.name] = field_value }
      transformer.call(csv_value, model, column)
    else
      raise ArgumentError, "arity: #{transformer.arity.inspect} - `to` can only have 1, 2 or 3 arguments"
    end
  else
    attribute = column_definition.attribute
    model.public_send("#{attribute}=", csv_value)
  end

  model
end

#set_attributes(model) ⇒ Object

Set attributes



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/csv_importer/row.rb', line 35

def set_attributes(model)
  header.columns.each do |column|
    value = csv_attributes[column.name]
    begin
      value = value.dup if value
    rescue TypeError
      # can't dup Symbols, Integer etc...
    end

    next if column.definition.nil?

    set_attribute(model, column, value)
  end

  model
end

#skip!Object



113
114
115
# File 'lib/csv_importer/row.rb', line 113

def skip!
  self.skip = true
end