activerecord-import 1.2.0 → 1.3.0
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 +4 -4
- data/.github/workflows/test.yaml +8 -3
- data/CHANGELOG.md +13 -0
- data/Gemfile +1 -1
- data/activerecord-import.gemspec +2 -2
- data/gemfiles/6.1.gemfile +1 -0
- data/gemfiles/7.0.gemfile +1 -0
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +0 -2
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +0 -2
- data/lib/activerecord-import/import.rb +26 -13
- data/lib/activerecord-import/synchronize.rb +1 -1
- data/lib/activerecord-import/version.rb +1 -1
- data/test/models/customer.rb +6 -0
- data/test/models/order.rb +6 -0
- data/test/schema/generic_schema.rb +11 -0
- data/test/support/postgresql/import_examples.rb +24 -0
- data/test/support/shared_examples/recursive_import.rb +21 -1
- metadata +14 -12
- data/gemfiles/3.2.gemfile +0 -2
- data/gemfiles/4.0.gemfile +0 -2
- data/gemfiles/4.1.gemfile +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 815280c3b17a8ee84e54defd450a68fa532719dc8760ac001883f3df0156d689
|
|
4
|
+
data.tar.gz: d34ee8c4c186b172259ea4f3427a75379d08b7ae41ee67128fd870e489d2f78d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 49c6d78cbcdc342db44497ec66f0dfe466b08124dc233996688c9443b0c455328e6d7ebc80d011c8732f7ae5b5468bd3c4f57f4abe2bb20bc26a118183cea402
|
|
7
|
+
data.tar.gz: 9f602bb4423fb3cc5169727d150df7eef5396954f0576f1ecf8cb168179adc625f5ef5927a4655eb8271e37d845d9e5c6b6a6a597a83cb1c268958b4f2f65375
|
data/.github/workflows/test.yaml
CHANGED
|
@@ -20,13 +20,18 @@ jobs:
|
|
|
20
20
|
fail-fast: false
|
|
21
21
|
matrix:
|
|
22
22
|
ruby:
|
|
23
|
-
- 2.
|
|
23
|
+
- 2.7
|
|
24
24
|
env:
|
|
25
|
+
- AR_VERSION: 7.0
|
|
25
26
|
- AR_VERSION: 6.1
|
|
26
27
|
- AR_VERSION: 6.0
|
|
27
|
-
- AR_VERSION: 5.2
|
|
28
|
-
- AR_VERSION: 5.1
|
|
29
28
|
include:
|
|
29
|
+
- ruby: 2.6
|
|
30
|
+
env:
|
|
31
|
+
AR_VERSION: 5.2
|
|
32
|
+
- ruby: 2.6
|
|
33
|
+
env:
|
|
34
|
+
AR_VERSION: 5.1
|
|
30
35
|
- ruby: 2.4
|
|
31
36
|
env:
|
|
32
37
|
AR_VERSION: 5.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## Changes in 1.3.0
|
|
2
|
+
|
|
3
|
+
### Fixes
|
|
4
|
+
|
|
5
|
+
* Ensure correct timestamp values are returned for models after insert. Thanks to @kos1kov via \##756.
|
|
6
|
+
* Restore database_version method to public scope. Thanks to @beauraF via \##753.
|
|
7
|
+
|
|
8
|
+
### New Features
|
|
9
|
+
|
|
10
|
+
* Add support for ActiveRecord 7.0. Thanks to @nickhammond, @ryanwood, @jkowens via \##749 and \##752.
|
|
11
|
+
* Add support for compound foreign keys. Thanks to @Uladzimiro via \##750.
|
|
12
|
+
* Add support for :recursive combined with on_duplicate_key_update: :all. Thanks to @deathwish via \##746.
|
|
13
|
+
|
|
1
14
|
## Changes in 1.2.0
|
|
2
15
|
|
|
3
16
|
### Fixes
|
data/Gemfile
CHANGED
data/activerecord-import.gemspec
CHANGED
|
@@ -16,8 +16,8 @@ Gem::Specification.new do |gem|
|
|
|
16
16
|
gem.require_paths = ["lib"]
|
|
17
17
|
gem.version = ActiveRecord::Import::VERSION
|
|
18
18
|
|
|
19
|
-
gem.required_ruby_version = ">= 2.
|
|
19
|
+
gem.required_ruby_version = ">= 2.4.0"
|
|
20
20
|
|
|
21
|
-
gem.add_runtime_dependency "activerecord", ">=
|
|
21
|
+
gem.add_runtime_dependency "activerecord", ">= 4.2"
|
|
22
22
|
gem.add_development_dependency "rake"
|
|
23
23
|
end
|
data/gemfiles/6.1.gemfile
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gem 'activerecord', '~> 7.0.0.alpha2'
|
|
@@ -166,8 +166,6 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
|
166
166
|
exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('duplicate key')
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
private
|
|
170
|
-
|
|
171
169
|
def database_version
|
|
172
170
|
defined?(sqlite_version) ? sqlite_version : super
|
|
173
171
|
end
|
|
@@ -34,7 +34,7 @@ module ActiveRecord::Import #:nodoc:
|
|
|
34
34
|
@validate_callbacks = klass._validate_callbacks.dup
|
|
35
35
|
|
|
36
36
|
@validate_callbacks.each_with_index do |callback, i|
|
|
37
|
-
filter = callback.raw_filter
|
|
37
|
+
filter = callback.respond_to?(:raw_filter) ? callback.raw_filter : callback.filter
|
|
38
38
|
next unless filter.class.name =~ /Validations::PresenceValidator/ ||
|
|
39
39
|
(!@options[:validate_uniqueness] &&
|
|
40
40
|
filter.is_a?(ActiveRecord::Validations::UniquenessValidator))
|
|
@@ -734,7 +734,10 @@ class ActiveRecord::Base
|
|
|
734
734
|
set_attributes_and_mark_clean(models, return_obj, timestamps, options)
|
|
735
735
|
|
|
736
736
|
# if there are auto-save associations on the models we imported that are new, import them as well
|
|
737
|
-
|
|
737
|
+
if options[:recursive]
|
|
738
|
+
options[:on_duplicate_key_update] = on_duplicate_key_update unless on_duplicate_key_update.nil?
|
|
739
|
+
import_associations(models, options.dup.merge(validate: false))
|
|
740
|
+
end
|
|
738
741
|
end
|
|
739
742
|
|
|
740
743
|
return_obj
|
|
@@ -854,7 +857,7 @@ class ActiveRecord::Base
|
|
|
854
857
|
model.id = id
|
|
855
858
|
|
|
856
859
|
timestamps.each do |attr, value|
|
|
857
|
-
model.send(attr + "=", value)
|
|
860
|
+
model.send(attr + "=", value) if model.send(attr).nil?
|
|
858
861
|
end
|
|
859
862
|
end
|
|
860
863
|
end
|
|
@@ -908,15 +911,19 @@ class ActiveRecord::Base
|
|
|
908
911
|
changed_columns = model.changed
|
|
909
912
|
association_reflections = model.class.reflect_on_all_associations(:belongs_to)
|
|
910
913
|
association_reflections.each do |association_reflection|
|
|
911
|
-
column_name = association_reflection.foreign_key
|
|
912
914
|
next if association_reflection.options[:polymorphic]
|
|
913
|
-
next if changed_columns.include?(column_name)
|
|
914
|
-
association = model.association(association_reflection.name)
|
|
915
|
-
association = association.target
|
|
916
|
-
next if association.blank? || model.public_send(column_name).present?
|
|
917
915
|
|
|
918
|
-
|
|
919
|
-
|
|
916
|
+
column_names = Array(association_reflection.foreign_key).map(&:to_s)
|
|
917
|
+
column_names.each_with_index do |column_name, column_index|
|
|
918
|
+
next if changed_columns.include?(column_name)
|
|
919
|
+
|
|
920
|
+
association = model.association(association_reflection.name)
|
|
921
|
+
association = association.target
|
|
922
|
+
next if association.blank? || model.public_send(column_name).present?
|
|
923
|
+
|
|
924
|
+
association_primary_key = Array(association_reflection.association_primary_key)[column_index]
|
|
925
|
+
model.public_send("#{column_name}=", association.send(association_primary_key))
|
|
926
|
+
end
|
|
920
927
|
end
|
|
921
928
|
end
|
|
922
929
|
|
|
@@ -929,8 +936,9 @@ class ActiveRecord::Base
|
|
|
929
936
|
associated_objects_by_class = {}
|
|
930
937
|
models.each { |model| find_associated_objects_for_import(associated_objects_by_class, model) }
|
|
931
938
|
|
|
932
|
-
# :on_duplicate_key_update
|
|
933
|
-
options.delete(:on_duplicate_key_update)
|
|
939
|
+
# :on_duplicate_key_update only supported for all fields
|
|
940
|
+
options.delete(:on_duplicate_key_update) unless options[:on_duplicate_key_update] == :all
|
|
941
|
+
# :returning not supported for associations
|
|
934
942
|
options.delete(:returning)
|
|
935
943
|
|
|
936
944
|
associated_objects_by_class.each_value do |associations|
|
|
@@ -1029,7 +1037,12 @@ class ActiveRecord::Base
|
|
|
1029
1037
|
end
|
|
1030
1038
|
|
|
1031
1039
|
# use tz as set in ActiveRecord::Base
|
|
1032
|
-
|
|
1040
|
+
default_timezone = if ActiveRecord.respond_to?(:default_timezone)
|
|
1041
|
+
ActiveRecord.default_timezone
|
|
1042
|
+
else
|
|
1043
|
+
ActiveRecord::Base.default_timezone
|
|
1044
|
+
end
|
|
1045
|
+
timestamp = default_timezone == :utc ? Time.now.utc : Time.now
|
|
1033
1046
|
|
|
1034
1047
|
[:create, :update].each do |action|
|
|
1035
1048
|
timestamp_columns[action].each do |column|
|
|
@@ -39,7 +39,7 @@ module ActiveRecord # :nodoc:
|
|
|
39
39
|
|
|
40
40
|
next unless matched_instance
|
|
41
41
|
|
|
42
|
-
instance.
|
|
42
|
+
instance.instance_variable_set :@association_cache, {}
|
|
43
43
|
instance.send :clear_aggregation_cache if instance.respond_to?(:clear_aggregation_cache, true)
|
|
44
44
|
instance.instance_variable_set :@attributes, matched_instance.instance_variable_get(:@attributes)
|
|
45
45
|
|
|
@@ -205,4 +205,15 @@ ActiveRecord::Schema.define do
|
|
|
205
205
|
);
|
|
206
206
|
).split.join(' ').strip
|
|
207
207
|
end
|
|
208
|
+
|
|
209
|
+
create_table :customers, force: :cascade do |t|
|
|
210
|
+
t.integer :account_id
|
|
211
|
+
t.string :name
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
create_table :orders, force: :cascade do |t|
|
|
215
|
+
t.integer :account_id
|
|
216
|
+
t.integer :customer_id
|
|
217
|
+
t.integer :amount
|
|
218
|
+
end
|
|
208
219
|
end
|
|
@@ -290,6 +290,30 @@ def should_support_postgresql_import_functionality
|
|
|
290
290
|
assert_equal(binary_value, Alarm.first.secret_key)
|
|
291
291
|
end
|
|
292
292
|
end
|
|
293
|
+
|
|
294
|
+
unless ENV["SKIP_COMPOSITE_PK"]
|
|
295
|
+
describe "with composite foreign keys" do
|
|
296
|
+
let(:account_id) { 555 }
|
|
297
|
+
let(:customer) { Customer.new(account_id: account_id, name: "foo") }
|
|
298
|
+
let(:order) { Order.new(account_id: account_id, amount: 100, customer: customer) }
|
|
299
|
+
|
|
300
|
+
it "imports and correctly maps foreign keys" do
|
|
301
|
+
assert_difference "Customer.count", +1 do
|
|
302
|
+
Customer.import [customer]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
assert_difference "Order.count", +1 do
|
|
306
|
+
Order.import [order]
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
db_customer = Customer.last
|
|
310
|
+
db_order = Order.last
|
|
311
|
+
|
|
312
|
+
assert_equal db_customer.orders.last, db_order
|
|
313
|
+
assert_not_equal db_order.customer_id, nil
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
end
|
|
293
317
|
end
|
|
294
318
|
|
|
295
319
|
def should_support_postgresql_upsert_functionality
|
|
@@ -176,7 +176,7 @@ def should_support_recursive_import
|
|
|
176
176
|
end
|
|
177
177
|
end
|
|
178
178
|
|
|
179
|
-
# If adapter supports on_duplicate_key_update, it is only applied to top level models so that SQL with invalid
|
|
179
|
+
# If adapter supports on_duplicate_key_update and specific columns are specified, it is only applied to top level models so that SQL with invalid
|
|
180
180
|
# columns, keys, etc isn't generated for child associations when doing recursive import
|
|
181
181
|
if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
|
|
182
182
|
describe "on_duplicate_key_update" do
|
|
@@ -190,6 +190,26 @@ def should_support_recursive_import
|
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
end
|
|
193
|
+
|
|
194
|
+
context "when :all fields are updated" do
|
|
195
|
+
setup do
|
|
196
|
+
Topic.import new_topics, recursive: true
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "updates associated objects" do
|
|
200
|
+
new_author_name = 'Richard Bachman'
|
|
201
|
+
topic = new_topics.first
|
|
202
|
+
topic.books.each do |book|
|
|
203
|
+
book.author_name = new_author_name
|
|
204
|
+
end
|
|
205
|
+
assert_nothing_raised do
|
|
206
|
+
Topic.import new_topics, recursive: true, on_duplicate_key_update: :all
|
|
207
|
+
end
|
|
208
|
+
Topic.find(topic.id).books.each do |book|
|
|
209
|
+
assert_equal new_author_name, book.author_name
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
193
213
|
end
|
|
194
214
|
end
|
|
195
215
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-import
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zach Dennis
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-12-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '4.2'
|
|
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: '
|
|
26
|
+
version: '4.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -68,15 +68,13 @@ files:
|
|
|
68
68
|
- benchmarks/models/test_memory.rb
|
|
69
69
|
- benchmarks/models/test_myisam.rb
|
|
70
70
|
- benchmarks/schema/mysql2_schema.rb
|
|
71
|
-
- gemfiles/3.2.gemfile
|
|
72
|
-
- gemfiles/4.0.gemfile
|
|
73
|
-
- gemfiles/4.1.gemfile
|
|
74
71
|
- gemfiles/4.2.gemfile
|
|
75
72
|
- gemfiles/5.0.gemfile
|
|
76
73
|
- gemfiles/5.1.gemfile
|
|
77
74
|
- gemfiles/5.2.gemfile
|
|
78
75
|
- gemfiles/6.0.gemfile
|
|
79
76
|
- gemfiles/6.1.gemfile
|
|
77
|
+
- gemfiles/7.0.gemfile
|
|
80
78
|
- lib/activerecord-import.rb
|
|
81
79
|
- lib/activerecord-import/active_record/adapters/abstract_adapter.rb
|
|
82
80
|
- lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb
|
|
@@ -128,11 +126,13 @@ files:
|
|
|
128
126
|
- test/models/car.rb
|
|
129
127
|
- test/models/card.rb
|
|
130
128
|
- test/models/chapter.rb
|
|
129
|
+
- test/models/customer.rb
|
|
131
130
|
- test/models/deck.rb
|
|
132
131
|
- test/models/dictionary.rb
|
|
133
132
|
- test/models/discount.rb
|
|
134
133
|
- test/models/end_note.rb
|
|
135
134
|
- test/models/group.rb
|
|
135
|
+
- test/models/order.rb
|
|
136
136
|
- test/models/playing_card.rb
|
|
137
137
|
- test/models/promotion.rb
|
|
138
138
|
- test/models/question.rb
|
|
@@ -174,7 +174,7 @@ homepage: https://github.com/zdennis/activerecord-import
|
|
|
174
174
|
licenses:
|
|
175
175
|
- MIT
|
|
176
176
|
metadata: {}
|
|
177
|
-
post_install_message:
|
|
177
|
+
post_install_message:
|
|
178
178
|
rdoc_options: []
|
|
179
179
|
require_paths:
|
|
180
180
|
- lib
|
|
@@ -182,15 +182,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
182
182
|
requirements:
|
|
183
183
|
- - ">="
|
|
184
184
|
- !ruby/object:Gem::Version
|
|
185
|
-
version: 2.
|
|
185
|
+
version: 2.4.0
|
|
186
186
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
187
|
requirements:
|
|
188
188
|
- - ">="
|
|
189
189
|
- !ruby/object:Gem::Version
|
|
190
190
|
version: '0'
|
|
191
191
|
requirements: []
|
|
192
|
-
rubygems_version: 3.0.
|
|
193
|
-
signing_key:
|
|
192
|
+
rubygems_version: 3.0.3
|
|
193
|
+
signing_key:
|
|
194
194
|
specification_version: 4
|
|
195
195
|
summary: Bulk insert extension for ActiveRecord
|
|
196
196
|
test_files:
|
|
@@ -222,11 +222,13 @@ test_files:
|
|
|
222
222
|
- test/models/car.rb
|
|
223
223
|
- test/models/card.rb
|
|
224
224
|
- test/models/chapter.rb
|
|
225
|
+
- test/models/customer.rb
|
|
225
226
|
- test/models/deck.rb
|
|
226
227
|
- test/models/dictionary.rb
|
|
227
228
|
- test/models/discount.rb
|
|
228
229
|
- test/models/end_note.rb
|
|
229
230
|
- test/models/group.rb
|
|
231
|
+
- test/models/order.rb
|
|
230
232
|
- test/models/playing_card.rb
|
|
231
233
|
- test/models/promotion.rb
|
|
232
234
|
- test/models/question.rb
|
data/gemfiles/3.2.gemfile
DELETED
data/gemfiles/4.0.gemfile
DELETED
data/gemfiles/4.1.gemfile
DELETED