gunwale 0.7.0 → 0.8.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: 5c15189abadefbe716a46534ac6b66c672a975a77cbcf0f6edd662da3d0ba461
4
- data.tar.gz: 5033289d98349cef8d77c9cbf0bf4ab73f83547e195fffd36085260cfc172bb9
3
+ metadata.gz: e9d660c3c7d179b423ca59cb6e14a55f792d5cd71aef5e55b7443a702578a7e5
4
+ data.tar.gz: f430243b3bbe201f6b9ee72bf6658f4d94e474bc3996a2a4c7f2707f1451479d
5
5
  SHA512:
6
- metadata.gz: 3192566ce546a6ce436bbc3c7a5967f3a6c644617cdcc29092b3187ffa64506c92044d48ee68083174fb56bd2bf6a97c2b10b6e530fb197e3122bf4af9784357
7
- data.tar.gz: fb223ca48474086274562bf62475f35f60f2797c4c620e993716802fbaf909f569beb4288a240c213757f1d07013292fa2bef6b635087164e86a35513a04fc70
6
+ metadata.gz: e6d2ab13432f57eda0a2abdedfd971d30f40bfbadf9cca45f300a409dc4354d3e1ad4be0b26094cb97ad0df2079fe176f927142628285ad9e2fd585da1eef5ae
7
+ data.tar.gz: 79e34cac33ee1b1e515619a270e64845f251685e68568abe7fd124d9fd58716b98d96e948de200e1b681103e66856c563a2a6f32f690032f6dc6c233937ca9ca
data/db/schema.rb CHANGED
@@ -10,9 +10,9 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema[7.1].define(version: 2017_05_11_160154) do
13
+ ActiveRecord::Schema[8.0].define(version: 2017_05_11_160154) do
14
14
  # These are extensions that must be enabled in order to support this database
15
- enable_extension "plpgsql"
15
+ enable_extension "pg_catalog.plpgsql"
16
16
 
17
17
  create_table "products", force: :cascade do |t|
18
18
  t.string "name", null: false
@@ -22,5 +22,4 @@ ActiveRecord::Schema[7.1].define(version: 2017_05_11_160154) do
22
22
  t.datetime "updated_at", precision: nil, null: false
23
23
  t.index ["rank"], name: "index_products_on_rank", unique: true
24
24
  end
25
-
26
25
  end
data/lib/row_boat/base.rb CHANGED
@@ -8,6 +8,9 @@ module RowBoat
8
8
  class Base
9
9
  InvalidColumnMapping = Class.new(StandardError)
10
10
 
11
+ SENTINEL = :__ROWBOAT_ABSENT__
12
+ private_constant :SENTINEL
13
+
11
14
  attr_reader :csv_source
12
15
 
13
16
  class << self
@@ -110,6 +113,11 @@ module RowBoat
110
113
  def import_rows(rows)
111
114
  import_options = ::RowBoat::Helpers.extract_import_options(merged_options)
112
115
  preprocessed_rows = preprocess_rows(rows)
116
+
117
+ # Prevent "ON CONFLICT ... cannot affect row a second time" by
118
+ # deduplicating input rows on the declared conflict target.
119
+ preprocessed_rows = dedupe_on_conflict_target(preprocessed_rows, import_options)
120
+
113
121
  import_into.import(preprocessed_rows, import_options)
114
122
  end
115
123
 
@@ -300,6 +308,27 @@ module RowBoat
300
308
  end
301
309
  end
302
310
 
311
+ # Deduplicate rows on the activerecord-import conflict target (if any).
312
+ # Keeps the *last* occurrence for deterministic "last write wins" behavior.
313
+ def dedupe_on_conflict_target(rows, import_options)
314
+ return rows if rows.empty?
315
+
316
+ conflict_target = Array(import_options.dig(:on_duplicate_key_update, :conflict_target))
317
+ .map { |k| k.is_a?(Symbol) ? k : k.to_s.to_sym }
318
+ return rows if conflict_target.empty?
319
+
320
+ # If any row is not a Hash-like payload, we can’t safely dedupe.
321
+ return rows unless rows.all? { |r| r.is_a?(Hash) }
322
+
323
+ # Last row wins
324
+ seen = {}
325
+ rows.each do |r|
326
+ key = conflict_target.map { |k| r.key?(k) ? r[k] : SENTINEL }
327
+ seen[key] = r
328
+ end
329
+ seen.values
330
+ end
331
+
303
332
  # @api private
304
333
  # @private
305
334
  def process_import_results(import_results)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RowBoat
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.1"
5
5
  end
data/row_boat.gemspec CHANGED
@@ -22,14 +22,14 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "activerecord", "~> 8.0", "< 8.1"
26
- spec.add_dependency "activerecord-import", "~> 1.6"
27
- spec.add_dependency "smarter_csv", "~> 1.13", ">= 1.13.0"
25
+ spec.add_dependency "activerecord", ">= 7.1", "< 9.0"
26
+ spec.add_dependency "activerecord-import", ">= 1.6", "< 2.0"
27
+ spec.add_dependency "smarter_csv", ">= 1.13", "< 2.0"
28
28
 
29
29
  spec.add_development_dependency "appraisal", "~> 2.5"
30
30
  spec.add_development_dependency "awesome_print"
31
31
  spec.add_development_dependency "bundler", "~> 2.5.9"
32
- spec.add_development_dependency "database_cleaner", "~> 2.0", ">= 2.0.2"
32
+ spec.add_development_dependency "database_cleaner", "~> 2.1", ">= 2.1.0"
33
33
  spec.add_development_dependency "pg"
34
34
  spec.add_development_dependency "pry"
35
35
  spec.add_development_dependency "pry-doc"
@@ -37,6 +37,6 @@ Gem::Specification.new do |spec|
37
37
  spec.add_development_dependency "rake", "~> 13.2", ">= 13.2.1"
38
38
  spec.add_development_dependency "rspec", "~> 3.13"
39
39
  spec.add_development_dependency "rubocop", "~> 1.63", ">= 1.63.5"
40
- spec.add_development_dependency "standalone_migrations", "~> 8.0"
40
+ spec.add_development_dependency "standalone_migrations", ">= 7.1", "< 9.0"
41
41
  spec.add_development_dependency "yard", "~> 0.9.36"
42
42
  end
metadata CHANGED
@@ -1,69 +1,75 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gunwale
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlton Trezevant
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-15 00:00:00.000000000 Z
11
+ date: 2025-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '8.0'
19
+ version: '7.1'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '8.1'
22
+ version: '9.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "~>"
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '8.0'
29
+ version: '7.1'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '8.1'
32
+ version: '9.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activerecord-import
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "~>"
37
+ - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '1.6'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '2.0'
40
43
  type: :runtime
41
44
  prerelease: false
42
45
  version_requirements: !ruby/object:Gem::Requirement
43
46
  requirements:
44
- - - "~>"
47
+ - - ">="
45
48
  - !ruby/object:Gem::Version
46
49
  version: '1.6'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '2.0'
47
53
  - !ruby/object:Gem::Dependency
48
54
  name: smarter_csv
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - "~>"
57
+ - - ">="
52
58
  - !ruby/object:Gem::Version
53
59
  version: '1.13'
54
- - - ">="
60
+ - - "<"
55
61
  - !ruby/object:Gem::Version
56
- version: 1.13.0
62
+ version: '2.0'
57
63
  type: :runtime
58
64
  prerelease: false
59
65
  version_requirements: !ruby/object:Gem::Requirement
60
66
  requirements:
61
- - - "~>"
67
+ - - ">="
62
68
  - !ruby/object:Gem::Version
63
69
  version: '1.13'
64
- - - ">="
70
+ - - "<"
65
71
  - !ruby/object:Gem::Version
66
- version: 1.13.0
72
+ version: '2.0'
67
73
  - !ruby/object:Gem::Dependency
68
74
  name: appraisal
69
75
  requirement: !ruby/object:Gem::Requirement
@@ -112,20 +118,20 @@ dependencies:
112
118
  requirements:
113
119
  - - "~>"
114
120
  - !ruby/object:Gem::Version
115
- version: '2.0'
121
+ version: '2.1'
116
122
  - - ">="
117
123
  - !ruby/object:Gem::Version
118
- version: 2.0.2
124
+ version: 2.1.0
119
125
  type: :development
120
126
  prerelease: false
121
127
  version_requirements: !ruby/object:Gem::Requirement
122
128
  requirements:
123
129
  - - "~>"
124
130
  - !ruby/object:Gem::Version
125
- version: '2.0'
131
+ version: '2.1'
126
132
  - - ">="
127
133
  - !ruby/object:Gem::Version
128
- version: 2.0.2
134
+ version: 2.1.0
129
135
  - !ruby/object:Gem::Dependency
130
136
  name: pg
131
137
  requirement: !ruby/object:Gem::Requirement
@@ -240,16 +246,22 @@ dependencies:
240
246
  name: standalone_migrations
241
247
  requirement: !ruby/object:Gem::Requirement
242
248
  requirements:
243
- - - "~>"
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: '7.1'
252
+ - - "<"
244
253
  - !ruby/object:Gem::Version
245
- version: '8.0'
254
+ version: '9.0'
246
255
  type: :development
247
256
  prerelease: false
248
257
  version_requirements: !ruby/object:Gem::Requirement
249
258
  requirements:
250
- - - "~>"
259
+ - - ">="
260
+ - !ruby/object:Gem::Version
261
+ version: '7.1'
262
+ - - "<"
251
263
  - !ruby/object:Gem::Version
252
- version: '8.0'
264
+ version: '9.0'
253
265
  - !ruby/object:Gem::Dependency
254
266
  name: yard
255
267
  requirement: !ruby/object:Gem::Requirement
@@ -316,7 +328,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
328
  - !ruby/object:Gem::Version
317
329
  version: '0'
318
330
  requirements: []
319
- rubygems_version: 3.5.6
331
+ rubygems_version: 3.4.10
320
332
  signing_key:
321
333
  specification_version: 4
322
334
  summary: Turn the rows of your CSV into rows in your database