abstract_importer 1.5.6 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2273e7488017981f0caa7c51ae1bfc7fa2bf8dd3
4
- data.tar.gz: 0b2cf66310053405eace82238f10bc42b8af8dbf
2
+ SHA256:
3
+ metadata.gz: f1a26d52ad8e17f1b2539d5abbcf996a4c80ac157139a988fefd4a417c4fe03e
4
+ data.tar.gz: 388a9123f67dd9b52c35ae50a8added3c6995d2b8d71d703269dd317e13e8918
5
5
  SHA512:
6
- metadata.gz: 1d72f4017de21ff358da2f080289cb470b695ac0ee404bf2cd0a3fc6d04b71e1eb8ae38b3d3f98a93b574cd77737ffab17d3f63d1d4e30117c9e2edf18ff7d15
7
- data.tar.gz: fc0233f350e80133e8e699a17a95217a546b1de174baf7680ad925fde166a7637733ab509d6bf0bf174547038f54d496bfece1e9a55b6f9260514ca23791e81c
6
+ metadata.gz: 19531db43b5cd36a2831384fcef16092930b23cc9fa622c1aaa1b1bdc193d73df0d824deda4bdc5ce427d80272bd1d48cd972efea15011187fffa1c5720cb4cf
7
+ data.tar.gz: 14d9f5e0d630fc2e15be68bd83ef61ca610bf4cec4442af820cfa429915020320d88416af4c8f2fc5d7779daa8b83900c7b0be7e4a87bc21aa73985dd0a58c17
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.6.3
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.1
3
+ - 2.6.3
4
4
 
5
5
  # Use Postgres 9.5
6
6
  # https://www.brandur.org/fragments/postgres-95-travis
@@ -0,0 +1,2 @@
1
+ ## v1.6.0 (2019 Sept 23)
2
+ * BREAKING: Updated to use Rails 6 and its `insert_all` and `upsert_all` methods and arguments
data/README.md CHANGED
@@ -187,6 +187,23 @@ The following alternate strategies are built in:
187
187
 
188
188
  Replaces records that have already been imported rather than skipping them.
189
189
 
190
+ ##### insert
191
+
192
+ Bulk inserts records rather than creating them one-by-one as ActiveRecord objects, skipping those that have already been imported.
193
+
194
+ ##### upsert
195
+
196
+ Bulk inserts records, but updates records that have already been imported rather than skipping them.
197
+
198
+
199
+
200
+ ### Important Note on Upgrading from 1.5.x to 1.6.0
201
+
202
+ With the jump to 1.6.0, `abstract_importer` has dropped reliance upon the `activerecord-insert_many` gem in favor of taking advantage of Rails 6's built-in `insert_all` and `upsert_all` for the insert and upsert strategies. With the move from the gem to relying on Rails, the syntax to specify what constitutes a conflict/duplicate record has been updated to align more closely with that of Rails. In particular:
203
+
204
+ * Instead of specifying an `on_conflict: { do: :update }` clause, you should specify `on_duplicate: :update` to opt-in to upsert behavior.
205
+ * Rather than listing columns in `on_conflict: { columns: %i{legacy_id id} }`, you should use `unique_by: %i{legacy_id id}` to specify the index or columns by which a duplicate or conflict is defined. The option follows the behavior of Rails' `upsert_all`, so refer to the Rails 6 documentation for more information.
206
+
190
207
 
191
208
 
192
209
  ## Contributing
@@ -17,9 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "activerecord", ">= 5.0"
21
- spec.add_dependency "activesupport", ">= 5.0"
22
- spec.add_dependency "activerecord-insert_many", ">= 0.4.4"
20
+ spec.add_dependency "activerecord", ">= 6.0"
21
+ spec.add_dependency "activesupport", ">= 6.0"
23
22
  spec.add_dependency "progressbar"
24
23
 
25
24
  spec.add_development_dependency "bundler"
@@ -1,5 +1,4 @@
1
1
  require "abstract_importer/strategies/base"
2
- require "activerecord/insert_many"
3
2
 
4
3
  module AbstractImporter
5
4
  module Strategies
@@ -9,7 +8,8 @@ module AbstractImporter
9
8
  super
10
9
  @batch = []
11
10
  @batch_size = options.fetch(:batch_size, 250)
12
- @insert_options = options.slice(:on_conflict)
11
+ @bulk_operation = options[:on_duplicate] == :update ? :upsert_all : :insert_all
12
+ @insert_options = options.slice(:unique_by)
13
13
  @insert_options.merge!(returning: [:legacy_id, :id]) if remap_ids?
14
14
  end
15
15
 
@@ -52,7 +52,9 @@ module AbstractImporter
52
52
 
53
53
 
54
54
  def insert_batch(batch)
55
- result = collection.scope.insert_many(batch, @insert_options)
55
+ return if batch.empty?
56
+
57
+ result = collection.scope.public_send(@bulk_operation, batch, @insert_options)
56
58
  add_batch_to_id_map(result) if remap_ids?
57
59
  end
58
60
 
@@ -66,13 +68,26 @@ module AbstractImporter
66
68
 
67
69
 
68
70
  def add_batch_to_id_map(result)
69
- map = result.each_with_object({}) do |attrs, map|
71
+ map = cast_result(result, collection.table_name).each_with_object({}) do |attrs, map|
70
72
  map[attrs.fetch("legacy_id")] = attrs.fetch("id")
71
73
  end
72
74
  id_map.merge! collection.table_name, map
73
75
  end
74
76
 
75
77
 
78
+ def cast_result(result, table_name)
79
+ types_by_column = result.columns.each_with_object({}) do |column_name, types|
80
+ types[column_name] = collection.scope.connection.lookup_cast_type_from_column(collection.scope.columns.find { |column| column.name == column_name })
81
+ end
82
+
83
+ result.to_a.map { |row|
84
+ Hash[row.map { |column_name, value|
85
+ [ column_name, types_by_column[column_name].deserialize(value) ]
86
+ }]
87
+ }
88
+ end
89
+
90
+
76
91
  end
77
92
  end
78
93
  end
@@ -1,5 +1,4 @@
1
1
  require "abstract_importer/strategies/insert_strategy"
2
- require "activerecord/insert_many"
3
2
 
4
3
  module AbstractImporter
5
4
  module Strategies
@@ -7,7 +6,8 @@ module AbstractImporter
7
6
 
8
7
  def initialize(collection, options={})
9
8
  super
10
- @insert_options.reverse_merge!(on_conflict: { column: remap_ids? ? (association_attrs.keys + [:legacy_id]) : :id, do: :update })
9
+ @bulk_operation = :upsert_all
10
+ @insert_options.reverse_merge!(unique_by: remap_ids? ? (association_attrs.keys + %i{legacy_id}) : :id)
11
11
  end
12
12
 
13
13
  # We won't skip any records for already being imported
@@ -1,3 +1,3 @@
1
1
  module AbstractImporter
2
- VERSION = "1.5.6"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -17,7 +17,7 @@ class InsertStrategyTest < ActiveSupport::TestCase
17
17
  end
18
18
 
19
19
  should "import the records in batches" do
20
- mock.proxy(Student).insert_many(satisfy { |arg| arg.length == 3 }, anything)
20
+ mock.proxy(Student).insert_all(satisfy { |arg| arg.length == 3 }, anything)
21
21
  import!
22
22
  assert_equal [456, 457, 458], account.students.pluck(:legacy_id)
23
23
  end
@@ -54,6 +54,22 @@ class InsertStrategyTest < ActiveSupport::TestCase
54
54
  end
55
55
  end
56
56
 
57
+ context "With an empty data source" do
58
+ setup do
59
+ plan do |import|
60
+ import.students
61
+ end
62
+ @data_source = OpenStruct.new
63
+ @data_source.students = []
64
+ end
65
+
66
+ should "still be able to import" do
67
+ assert_nothing_raised do
68
+ import!
69
+ end
70
+ end
71
+ end
72
+
57
73
  context "When records already exist" do
58
74
  setup do
59
75
  plan do |import|
@@ -17,7 +17,7 @@ class UpsertStrategyTest < ActiveSupport::TestCase
17
17
  end
18
18
 
19
19
  should "import the records in batches" do
20
- mock.proxy(Student).insert_many(satisfy { |arg| arg.length == 3 }, anything)
20
+ mock.proxy(Student).upsert_all(satisfy { |arg| arg.length == 3 }, anything)
21
21
  import!
22
22
  assert_equal [456, 457, 458], account.students.pluck(:legacy_id)
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abstract_importer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Lail
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-16 00:00:00.000000000 Z
11
+ date: 2019-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,42 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5.0'
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5.0'
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5.0'
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '5.0'
41
- - !ruby/object:Gem::Dependency
42
- name: activerecord-insert_many
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 0.4.4
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 0.4.4
40
+ version: '6.0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: progressbar
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -230,6 +216,7 @@ files:
230
216
  - ".gitignore"
231
217
  - ".ruby-version"
232
218
  - ".travis.yml"
219
+ - CHANGELOG.md
233
220
  - Gemfile
234
221
  - LICENSE.txt
235
222
  - README.md
@@ -288,8 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
275
  - !ruby/object:Gem::Version
289
276
  version: '0'
290
277
  requirements: []
291
- rubyforge_project:
292
- rubygems_version: 2.5.1
278
+ rubygems_version: 3.0.3
293
279
  signing_key:
294
280
  specification_version: 4
295
281
  summary: Provides services for the mass-import of complex relational data