Module: CsvRowModel::Import::Attributes

Extended by:
ActiveSupport::Concern
Includes:
Model::Comparison
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

Methods included from Model::Comparison

#eql?, #hash

Class Method Details

.add_type_validation(column_name) ⇒ Object (protected)

Adds the type validation based on :validate_type option

Raises:

  • (ArgumentError)


101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/csv_row_model/import/attributes.rb', line 101

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

.default_lambda(column_name) ⇒ Lambda

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

Returns:

  • (Lambda)

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



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

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:

  • column_name (Symbol)

    the cell's column_name



95
96
97
98
# File 'lib/csv_row_model/import/attributes.rb', line 95

def define_attribute_method(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:

  • cell (String)

    the cell's string

  • column_name (Symbol)

    the cell's column_name

  • column_index (Integer)

    the column_name's index



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

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

.parse_lambda(column_name) ⇒ Lambda, Proc

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

Returns:

  • (Lambda, Proc)

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

Raises:

  • (ArgumentError)


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

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 CsvRowModel::Import.column's default option': column_name -> [value_before_default, default_set]



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

def default_changes
  original_attributes
  @default_changes
end

#original_attribute(column_name) ⇒ Object

Returns the column's attribute before override.

Returns:

  • (Object)

    the column's attribute before override



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

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:



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

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:

  • (Hash)

    a map of column_name => original_attribute(column_name)



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

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