data_porter 2.9.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d3f44f3aff296ae20b7ac78c00d4a9c6f12b2477837a7323528b26c75fd03d3
4
- data.tar.gz: 305de334f31a96b2e9c26e74ba58974420957df85d5169ce2de51a017b1f3622
3
+ metadata.gz: a04398e443f704b747eff3f3b585e05f839cabd2f92ecf7871874811a079f15c
4
+ data.tar.gz: ade55b5a550d628acaf5f8d0e8cc0652fabcb2c7505b59bd14367e7ab56557cf
5
5
  SHA512:
6
- metadata.gz: 702e623e0983e44a9f4b149f47d8426d667cb553b12ed5eb781b99d8072944abe3bbf415e724d44ce9a086bf9b2dcf62efd031b83cfa5613b7ab5efe26604b43
7
- data.tar.gz: 0a72e5ad9983833ffe451c076bafa07d1f433460b3b6020b6e9dcac0a20f263dbd73c0f796dfae3b52d08caeae11c531af510b70fd35880522da0ccda1a12e0a
6
+ metadata.gz: 9647861c80be730b057a74854c91569bbc2e6e7d922cff5bffd28d7d4268f2a55e83bc08247b4ea93b2c9991e1ac2da1da3f4e71970b71225d9c08e5440ca7d6
7
+ data.tar.gz: b96e83067441054e1a0140c7b826043984d7fcc0d6c7b7f7ee7fe2a09d416365670a7bce7ed1eeb703d6949ee9dd24d7c791b06978d12d8c52929fa17b4553c6
data/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.9.1] - 2026-03-11
11
+
12
+ ### Changed
13
+
14
+ - **Record data keys normalized to strings** -- `record.data` now uses `HashWithIndifferentAccess`, so both `record.data["key"]` and `record.data[:key]` work consistently. Sources, RecordBuilder, ColumnTransformer, and RecordValidator all produce string keys. No breaking change for existing Targets
15
+ - **Delete on mapping and preview** -- Imports in `mapping` and `previewing` status now show a Delete button with confirmation. Previously only `completed` and `failed` imports could be deleted. The preview Cancel button (which set status to `failed` without deleting) is replaced by Delete
16
+
10
17
  ## [2.9.0] - 2026-03-11
11
18
 
12
19
  ### Added
@@ -42,6 +42,11 @@
42
42
  templates: @templates,
43
43
  default_mapping: @default_mapping
44
44
  ).call %>
45
+ <div class="dp-actions">
46
+ <%= button_to t("data_porter.imports.delete"), import_path(@import),
47
+ method: :delete, class: "dp-btn dp-btn--danger",
48
+ data: { turbo_confirm: t("data_porter.imports.delete_confirm") } %>
49
+ </div>
45
50
  <% end %>
46
51
 
47
52
  <% if @import.previewing? %>
@@ -71,8 +76,9 @@
71
76
  <%= button_to t("data_porter.imports.back_to_mapping"), back_to_mapping_import_path(@import),
72
77
  method: :post, class: "dp-btn dp-btn--secondary" %>
73
78
  <% end %>
74
- <%= button_to t("data_porter.imports.cancel"), cancel_import_path(@import),
75
- method: :post, class: "dp-btn dp-btn--danger" %>
79
+ <%= button_to t("data_porter.imports.delete"), import_path(@import),
80
+ method: :delete, class: "dp-btn dp-btn--danger",
81
+ data: { turbo_confirm: t("data_porter.imports.delete_confirm") } %>
76
82
  </div>
77
83
  <% end %>
78
84
 
@@ -41,10 +41,8 @@ module DataPorter
41
41
  end
42
42
 
43
43
  def self.resolve_key(data, name)
44
- return name.to_s if data.key?(name.to_s)
45
- return name if data.key?(name)
46
-
47
- nil
44
+ key = name.to_s
45
+ key if data.key?(key)
48
46
  end
49
47
 
50
48
  def self.custom_transformers
@@ -72,7 +72,7 @@ module DataPorter
72
72
  end
73
73
 
74
74
  def cell_value(record, col)
75
- (record.data[col.name.to_s] || record.data[col.name]).to_s
75
+ record.data[col.name.to_s].to_s
76
76
  end
77
77
 
78
78
  def row_attrs(record)
@@ -40,7 +40,7 @@ module DataPorter
40
40
 
41
41
  def extract_data(row, columns)
42
42
  columns.each_with_object({}) do |col, hash|
43
- hash[col.name] = row[col.name] || row[col.name.to_s]
43
+ hash[col.name.to_s] = row[col.name.to_s] || row[col.name]
44
44
  end
45
45
  end
46
46
  end
@@ -24,9 +24,10 @@ module DataPorter
24
24
  def normalize_keys(record)
25
25
  @columns.each do |col|
26
26
  string_key = col.name.to_s
27
- next unless record.data.key?(string_key) && !record.data.key?(col.name)
27
+ next if record.data.key?(string_key)
28
+ next unless record.data.key?(col.name)
28
29
 
29
- record.data[col.name] = record.data.delete(string_key)
30
+ record.data[string_key] = record.data.delete(col.name)
30
31
  end
31
32
  end
32
33
  end
@@ -32,10 +32,7 @@ module DataPorter
32
32
  record.data[key] = value
33
33
  end
34
34
 
35
- def resolve_key(data, column)
36
- return column.to_sym if data.key?(column.to_sym)
37
- return column.to_s if data.key?(column.to_s)
38
-
35
+ def resolve_key(_data, column)
39
36
  column.to_s
40
37
  end
41
38
 
@@ -8,7 +8,7 @@ module DataPorter
8
8
 
9
9
  def validate(record)
10
10
  @columns.each do |col|
11
- value = record.data[col.name]
11
+ value = record.data[col.name.to_s]
12
12
  validate_required(record, col, value)
13
13
  validate_type(record, col, value)
14
14
  end
@@ -13,7 +13,7 @@ module DataPorter
13
13
  records = extract_records(parsed, api)
14
14
 
15
15
  Array(records).map do |hash|
16
- hash.transform_keys { |k| k.parameterize(separator: "_").to_sym }
16
+ hash.transform_keys { |k| k.parameterize(separator: "_") }
17
17
  end
18
18
  end
19
19
 
@@ -32,18 +32,18 @@ module DataPorter
32
32
 
33
33
  def user_map(row)
34
34
  user_mapping.each_with_object({}) do |(header, column), hash|
35
- hash[column.to_sym] = row[header]
35
+ hash[column.to_s] = row[header]
36
36
  end
37
37
  end
38
38
 
39
39
  def explicit_map(row, mappings)
40
40
  mappings.each_with_object({}) do |(header, column), hash|
41
- hash[column] = row[header]
41
+ hash[column.to_s] = row[header]
42
42
  end
43
43
  end
44
44
 
45
45
  def auto_map(row)
46
- row.to_h.transform_keys { |k| k.parameterize(separator: "_").to_sym }
46
+ row.to_h.transform_keys { |k| k.parameterize(separator: "_") }
47
47
  end
48
48
 
49
49
  def header_row_index
@@ -15,7 +15,7 @@ module DataPorter
15
15
  records = extract_records(parsed)
16
16
 
17
17
  Array(records).map do |hash|
18
- hash.transform_keys { |k| k.parameterize(separator: "_").to_sym }
18
+ hash.transform_keys { |k| k.parameterize(separator: "_") }
19
19
  end
20
20
  end
21
21
 
@@ -10,8 +10,12 @@ module DataPorter
10
10
 
11
11
  attribute :line_number, :integer
12
12
  attribute :status, :string, default: "pending"
13
- attribute :data, default: -> { {} }
13
+ attribute :data, default: -> { HashWithIndifferentAccess.new }
14
14
  attribute :errors_list, Error.to_array_type, default: -> { [] }
15
+
16
+ def data=(value)
17
+ super(value.is_a?(Hash) ? value.with_indifferent_access : value)
18
+ end
15
19
  attribute :warnings, Error.to_array_type, default: -> { [] }
16
20
  attribute :target_id, :integer
17
21
  attribute :dry_run_passed, :boolean, default: false
@@ -29,7 +33,7 @@ module DataPorter
29
33
  end
30
34
 
31
35
  def attributes
32
- data.symbolize_keys.compact
36
+ data.stringify_keys.compact.with_indifferent_access
33
37
  end
34
38
 
35
39
  def determine_status!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DataPorter
4
- VERSION = "2.9.0"
4
+ VERSION = "2.9.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_porter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.0
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seryl Lounis