Module: CsvRowModel::Import::Attributes

Extended by:
ActiveSupport::Concern
Included in:
CsvRowModel::Import
Defined in:
lib/csv_row_model/import/attributes.rb

Constant Summary collapse

PARSE_VALIDATION_CLASSES =

Classes with a validations associated with them in csv_row_model/validators

[Boolean, Integer, Float, Date].freeze
CLASS_TO_PARSE_LAMBDA =

Mapping of column type classes to a parsing lambda. These are applied after Import.format_cell. Can pass custom Proc with :parse option.

{
  nil => ->(s) { s },
  Boolean => ->(s) { s =~ BooleanFormatValidator::FALSE_BOOLEAN_REGEX ? false : true },
  String  => ->(s) { s },
  Integer => ->(s) { s.to_i },
  Float   => ->(s) { s.to_f },
  Date    => ->(s) { s.present? ? Date.parse(s) : s }
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_type_validation(column_name) ⇒ Object (protected)

Adds the type validation based on :validate_type option

Raises:



113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/csv_row_model/import/attributes.rb', line 113

def add_type_validation(column_name)
  options = options(column_name)
  validate_type = options[:validate_type]

  return unless validate_type

  type = options[:type]
  raise ArgumentError.new("invalid :type given for :validate_type for column") unless PARSE_VALIDATION_CLASSES.include? type
  validate_type = Proc.new { validates column_name, "#{type.name.underscore}_format".to_sym => true, allow_blank: true }

  csv_string_model(&validate_type)
end

.column(column_name, options = {}) ⇒ Object (protected)

See Model#column



93
94
95
96
# File 'lib/csv_row_model/import/attributes.rb', line 93

def column(column_name, options={})
  super
  define_attribute_method(column_name)
end

.default_lambda(column_name) ⇒ Lambda

Returns a Lambda: ->(original_value) { default_exists? ? default : original_value }

Returns:

  • returns a Lambda: ->(original_value) { default_exists? ? default : original_value }



74
75
76
77
# File 'lib/csv_row_model/import/attributes.rb', line 74

def default_lambda(column_name)
  default = options(column_name)[:default]
  default.is_a?(Proc) ? ->(s) { instance_exec(&default) } : ->(s) { default.nil? ? s : default }
end

.define_attribute_method(column_name) ⇒ Object (protected)

Define default attribute method for a column

Parameters:

  • the cell's column_name



106
107
108
109
110
# File 'lib/csv_row_model/import/attributes.rb', line 106

def define_attribute_method(column_name)
  return if method_defined? column_name
  add_type_validation(column_name)
  define_method(column_name) { original_attribute(column_name) }
end

.format_cell(cell, column_name, column_index, context = {}) ⇒ Object

Safe to override. Method applied to each cell by default

Parameters:

  • the cell's string

  • the cell's column_name

  • the column_name's index



69
70
71
# File 'lib/csv_row_model/import/attributes.rb', line 69

def format_cell(cell, column_name, column_index, context={})
  cell
end

.merge_options(column_name, options = {}) ⇒ Object (protected)



98
99
100
101
102
# File 'lib/csv_row_model/import/attributes.rb', line 98

def merge_options(column_name, options={})
  original_options = options(column_name)
  add_type_validation(column_name) if !original_options[:validate_type] && options[:validate_type]
  super
end

.parse_lambda(column_name) ⇒ Lambda, Proc

->(original_value) { parse_proc_exists? ? parsed_value : original_value }

Returns:

  • returns the Lambda/Proc given in the parse option or:

Raises:



81
82
83
84
85
86
87
88
89
# File 'lib/csv_row_model/import/attributes.rb', line 81

def parse_lambda(column_name)
  options = options(column_name)

  raise ArgumentError.new("You need either :parse OR :type but not both of them") if options[:parse] && options[:type]

  parse_lambda = options[:parse] || CLASS_TO_PARSE_LAMBDA[options[:type]]
  return parse_lambda if parse_lambda
  raise ArgumentError.new("type must be #{CLASS_TO_PARSE_LAMBDA.keys.reject(:nil?).join(", ")}")
end

Instance Method Details

#default_changesObject

return [Hash] a map changes from column's default option': column_name -> [value_before_default, default_set]



51
52
53
54
# File 'lib/csv_row_model/import/attributes.rb', line 51

def default_changes
  original_attributes
  @default_changes
end

#original_attribute(column_name) ⇒ Object

Returns the column's attribute before override.

Returns:

  • the column's attribute before override



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/csv_row_model/import/attributes.rb', line 33

def original_attribute(column_name)
  return @original_attributes[column_name] if original_attribute_memoized? column_name

  csv_string_model.valid?
  return nil unless csv_string_model.errors[column_name].blank?

  value = self.class.format_cell(mapped_row[column_name], column_name, self.class.index(column_name), context)
  if value.present?
    value = instance_exec(value, &self.class.parse_lambda(column_name))
  elsif self.class.options(column_name)[:default]
    original_value = value
    value = instance_exec(value, &self.class.default_lambda(column_name))
    @default_changes[column_name] = [original_value, value]
  end
  @original_attributes[column_name] = value
end

#original_attribute_memoized?(column_name) ⇒ Boolean (protected)

Returns:



57
58
59
60
61
# File 'lib/csv_row_model/import/attributes.rb', line 57

def original_attribute_memoized?(column_name)
  @original_attributes ||= {}
  @default_changes     ||= {}
  @original_attributes.has_key? column_name
end

#original_attributesHash

Returns a map of column_name => original_attribute(column_name).

Returns:

  • a map of column_name => original_attribute(column_name)



27
28
29
30
# File 'lib/csv_row_model/import/attributes.rb', line 27

def original_attributes
  self.class.column_names.each { |column_name| original_attribute(column_name) }
  @original_attributes
end