activerecord-import 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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