Class: LcpRuby::Import::RowProcessor

Inherits:
Object
  • Object
show all
Defined in:
lib/lcp_ruby/import/row_processor.rb

Overview

Processes a single row from an import file: coerce types, resolve associations, apply strategy.

Instance Method Summary collapse

Constructor Details

#initialize(model_class:, model_definition:, column_mapping:, lookup_config:, strategy:, match_attribute:, value_coercer:, nested_blank_strategy: "null") ⇒ RowProcessor

Returns a new instance of RowProcessor.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/lcp_ruby/import/row_processor.rb', line 5

def initialize(model_class:, model_definition:, column_mapping:, lookup_config:,
               strategy:, match_attribute:, value_coercer:, nested_blank_strategy: "null")
  @model_class = model_class
  @model_definition = model_definition
  @column_mapping = column_mapping     # { "Source Col" => "field_name" }
  @lookup_config = lookup_config || {} # { "category_id" => "name" }
  @strategy = strategy
  @match_attribute = match_attribute
  @value_coercer = value_coercer
  @nested_blank_strategy = nested_blank_strategy
  @field_defs = build_field_defs_cache

  # Pre-compute nested association names for eager loading
  @nested_association_names = @column_mapping.values
    .select { |f| f.include?(".") }
    .map { |f| f.split(".", 2).first.to_sym }
    .uniq
end

Instance Method Details

#empty_row?(raw_row) ⇒ Boolean

Check if a row is completely empty (all mapped values are blank).

Returns:

  • (Boolean)


64
65
66
67
68
69
# File 'lib/lcp_ruby/import/row_processor.rb', line 64

def empty_row?(raw_row)
  @column_mapping.all? do |source_col, _field_name|
    val = raw_row[source_col]
    val.nil? || (val.is_a?(String) && val.strip.empty?)
  end
end

#process(raw_row) ⇒ Hash

Process a single row.

Parameters:

  • raw_row (Hash)

    { “Source Col” => “raw value” }

Returns:

  • (Hash)

    { status:, target_record_id:, error_message:, previous_values: }



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/lcp_ruby/import/row_processor.rb', line 27

def process(raw_row)
  attrs = coerce_row(raw_row)
  attrs = resolve_associations(attrs)

  case @strategy
  when "create_only"
    create_record(attrs)
  when "update_only"
    update_record(attrs)
  when "upsert"
    upsert_record(attrs)
  when "skip_existing"
    skip_existing_record(attrs)
  else
    { status: "error", target_record_id: nil,
      error_message: I18n.t("lcp_ruby.import.errors.unknown_strategy",
                            strategy: @strategy,
                            default: "Unknown strategy: %{strategy}"),
      previous_values: nil }
  end
rescue ValueCoercer::CoercionError => e
  { status: "error", target_record_id: nil, error_message: e.message, previous_values: nil }
rescue ActiveRecord::RecordNotUnique => e
  { status: "error", target_record_id: nil,
    error_message: I18n.t("lcp_ruby.import.errors.duplicate_record",
                          reason: e.message,
                          default: "Duplicate record: %{reason}"),
    previous_values: nil }
rescue StandardError => e
  { status: "error", target_record_id: nil,
    error_message: I18n.t("lcp_ruby.import.errors.row_failure",
                          error_class: e.class.to_s, reason: e.message,
                          default: "%{error_class}: %{reason}"),
    previous_values: nil }
end