Class: ImpExp::Importers::Base

Inherits:
Object
  • Object
show all
Includes:
Observable
Defined in:
app/services/imp_exp/importers/base.rb

Direct Known Subclasses

Xlsx

Constant Summary collapse

ROW_OFFSET =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scoping_parent, models, logger: nil, exception_notifier: nil) ⇒ Base

Returns a new instance of Base.



14
15
16
17
18
19
# File 'app/services/imp_exp/importers/base.rb', line 14

def initialize(scoping_parent, models, logger: nil, exception_notifier: nil)
  @scoping_parent = scoping_parent
  @models = models
  @logger = logger || Logger.new('log/imports.log', 1)
  @exception_notifier = exception_notifier
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def errors
  @errors
end

#exception_notifierObject (readonly)

Returns the value of attribute exception_notifier.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def exception_notifier
  @exception_notifier
end

#importedObject (readonly)

Returns the value of attribute imported.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def imported
  @imported
end

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def logger
  @logger
end

#modelsObject (readonly)

Returns the value of attribute models.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def models
  @models
end

#scoping_parentObject (readonly)

Returns the value of attribute scoping_parent.



10
11
12
# File 'app/services/imp_exp/importers/base.rb', line 10

def scoping_parent
  @scoping_parent
end

Instance Method Details

#call(data, files_directory_path = nil) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'app/services/imp_exp/importers/base.rb', line 21

def call(data, files_directory_path = nil)
  @errors = []
  @imported = data.keys.map(&:model_name).index_with { 0 }
  logger.info "Starting import #{self.class.name} for #{scoping_parent.model_name.singular} " \
              "#{scoping_parent.name} (#{scoping_parent.id})"
  begin
    ping(stage: 'validation')
    import(data, files_directory_path)
    logger.info "Import completed\n---------"
    import_result
  rescue StandardError => e
    logger.error "Import interrupted with error : #{e.class.name} #{e.message}:"
    logger.error e.backtrace.join("\n")

    raise e if raise_rescued_standard_error?

    exception_notifier&.call(e)
    import_result.merge(exception_raised: "#{e.class.name} #{e.message}")
  end
end

#import(data, files_directory_path) ⇒ Object



42
43
44
45
46
47
# File 'app/services/imp_exp/importers/base.rb', line 42

def import(data, files_directory_path)
  data.each do |model, model_data|
    ping(forced: true, stage: 'import', model_name: model.model_name)
    import_model_data(model, model_data, files_directory_path)
  end
end

#import_model_data(model, model_data, files_directory_path) ⇒ Object

rubocop:disable Metrics/MethodLength



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
# File 'app/services/imp_exp/importers/base.rb', line 53

def import_model_data(model, model_data, files_directory_path) # rubocop:disable Metrics/MethodLength
  model_data.each_with_index do |row, i|
    line = ROW_OFFSET + i + 1
    model_name = model.model_name

    relation_attributes = model.relation_names.index_with do |relation_name|
      relation_attribute(model, relation_name, row[relation_name])
    end

    relation_attributes = process_errors(relation_attributes, model, line, row.to_s)

    attrs = attributes_from_row(row, model).merge!(relation_attributes)

    record = find_or_initialize_record(row.merge(relation_attributes), scoping_parent, model)

    upsert_no_record_error(row, model, line) && next unless record

    assign_attributes(record, attrs, model_name, line, row)

    record.assign_attributes(model.extra_attributes_imported_at_runtime(scoping_parent, record, row))

    serialize_attributes_if_needed(record, row, model)

    attach_files(record, files_directory_path, model, row, line) if files_directory_path.present?

    if record.save(context: :import)
      model.after_save(record)
      @imported[model.model_name] += 1
      next
    end

    upsert_error_messages(model_name, line, row.to_s, record.errors.full_messages)
  end
end

#import_resultObject



49
50
51
# File 'app/services/imp_exp/importers/base.rb', line 49

def import_result
  { imported: imported, import_errors: errors }
end