Class: AdvancedAR::BatchingCsvProcessor

Inherits:
Object
  • Object
show all
Defined in:
lib/advanced_ar/batching_csv_processor.rb

Defined Under Namespace

Classes: RowError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(csv, file_name: nil) ⇒ BatchingCsvProcessor

Returns a new instance of BatchingCsvProcessor.



7
8
9
10
# File 'lib/advanced_ar/batching_csv_processor.rb', line 7

def initialize(csv, file_name: nil)
  @csv = csv
  @file_name = file_name
end

Instance Attribute Details

#csvObject

Returns the value of attribute csv.



3
4
5
# File 'lib/advanced_ar/batching_csv_processor.rb', line 3

def csv
  @csv
end

#file_nameObject

Returns the value of attribute file_name.



3
4
5
# File 'lib/advanced_ar/batching_csv_processor.rb', line 3

def file_name
  @file_name
end

Class Method Details

.file_matches?(file) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
80
# File 'lib/advanced_ar/batching_csv_processor.rb', line 76

def self.file_matches?(file)
  header = file.readline.strip.split(',')
  file.try(:rewind)
  headers_match?(header)
end

.headers_match?(headers) ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/advanced_ar/batching_csv_processor.rb', line 82

def self.headers_match?(headers)
  (self::HEADERS - headers).empty?
end

Instance Method Details

#apply_row_to_model(_row, _instance) ⇒ Object

Raises:

  • (NotImplementedError)


29
30
31
# File 'lib/advanced_ar/batching_csv_processor.rb', line 29

def apply_row_to_model(_row, _instance)
  raise NotImplementedError
end

#batch_rows_to_models(rows) ⇒ Object



47
48
49
# File 'lib/advanced_ar/batching_csv_processor.rb', line 47

def batch_rows_to_models(rows)
  rows.map { |row| build_model_from_row(row) }.reject! { |inst| inst.nil? || !inst.changed? }
end

#build_model_from_row(row) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/advanced_ar/batching_csv_processor.rb', line 51

def build_model_from_row(row)
  model = find_or_init(row)
  apply_row_to_model(row, model)
  return nil if model.respond_to?(:discarded_at) && model.discarded_at.present? && !model.persisted?

  model
rescue ActiveRecord::RecordNotFound, RowError => err
  log_line_error(err.message, row[:line_number], exception: err)
  nil
rescue StandardError => err
  log_line_error('An Internal Error Occurred', row[:line_number], exception: err)
  Raven.capture_exception(err)
  nil
end

#find_or_init(_row) ⇒ Object

Raises:

  • (NotImplementedError)


25
26
27
# File 'lib/advanced_ar/batching_csv_processor.rb', line 25

def find_or_init(_row)
  raise NotImplementedError
end

#get_row_errors(row) ⇒ Object



23
# File 'lib/advanced_ar/batching_csv_processor.rb', line 23

def get_row_errors(row); end

#log_line_error(message, line_number, **kwargs) ⇒ Object

Raises:

  • (NotImplementedError)


33
34
35
# File 'lib/advanced_ar/batching_csv_processor.rb', line 33

def log_line_error(message, line_number, **kwargs)
  raise NotImplementedError
end

#map_defined_columns(row, map) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/advanced_ar/batching_csv_processor.rb', line 66

def map_defined_columns(row, map)
  newh = {}
  map.each do |newk, oldk|
    next unless row.include?(oldk)

    newh[newk] = row[oldk]
  end
  newh
end

#process_in_batches(&blk) ⇒ Object



12
13
14
15
16
17
18
19
20
21
# File 'lib/advanced_ar/batching_csv_processor.rb', line 12

def process_in_batches(&blk)
  batch = BatchProcessor.new(&blk)
  CSV.new(csv, headers: true, header_converters: :symbol).each.with_index do |row, line|
    row[:line_number] = line + 1
    next unless validate_line(row)

    batch << row
  end
  batch.flush
end

#validate_line(row) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/advanced_ar/batching_csv_processor.rb', line 37

def validate_line(row)
  errors = get_row_errors(row) || []
  if errors.present?
    log_line_error(errors[0], row[:line_number])
    false
  else
    true
  end
end