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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3360334cbd71089351c8211214bb4aedf0bd3e65305513b17c9fb09e3f1cf19
4
- data.tar.gz: 2b97e3a1c6c2b39970dd3bb2a00a608d6e105cddac19d3f9ebaf28f8f30ece69
3
+ metadata.gz: 815280c3b17a8ee84e54defd450a68fa532719dc8760ac001883f3df0156d689
4
+ data.tar.gz: d34ee8c4c186b172259ea4f3427a75379d08b7ae41ee67128fd870e489d2f78d
5
5
  SHA512:
6
- metadata.gz: 4585ba6ff2300d94fbd646d5f5a07cc254311cb9a47eacc7b1266eab8df5d9a53ca3018232e6c2517f05e1aef0dafaff20942bd1150ef518d688940f795bf2a9
7
- data.tar.gz: 532506d134f067323d0490a913739089e55bf17893f602c752e5e963af2d7d799f5200a72cc48e7c780992e9f82c68273dc7af308034664ba898ed5292e199c4
6
+ metadata.gz: 49c6d78cbcdc342db44497ec66f0dfe466b08124dc233996688c9443b0c455328e6d7ebc80d011c8732f7ae5b5468bd3c4f57f4abe2bb20bc26a118183cea402
7
+ data.tar.gz: 9f602bb4423fb3cc5169727d150df7eef5396954f0576f1ecf8cb168179adc625f5ef5927a4655eb8271e37d845d9e5c6b6a6a597a83cb1c268958b4f2f65375
@@ -20,13 +20,18 @@ jobs:
20
20
  fail-fast: false
21
21
  matrix:
22
22
  ruby:
23
- - 2.6
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
@@ -26,7 +26,7 @@ platforms :ruby do
26
26
  end
27
27
 
28
28
  platforms :jruby do
29
- gem 'jdbc-mysql', '< 8', require: false
29
+ gem "jdbc-mysql"
30
30
  gem "jdbc-postgres"
31
31
  gem "activerecord-jdbcsqlite3-adapter", "~> 1.3"
32
32
  gem "activerecord-jdbcmysql-adapter", "~> 1.3"
@@ -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.0.0"
19
+ gem.required_ruby_version = ">= 2.4.0"
20
20
 
21
- gem.add_runtime_dependency "activerecord", ">= 3.2"
21
+ gem.add_runtime_dependency "activerecord", ">= 4.2"
22
22
  gem.add_development_dependency "rake"
23
23
  end
data/gemfiles/6.1.gemfile CHANGED
@@ -1 +1,2 @@
1
1
  gem 'activerecord', '~> 6.1.0'
2
+ gem 'composite_primary_keys', '~> 13.0'
@@ -0,0 +1 @@
1
+ gem 'activerecord', '~> 7.0.0.alpha2'
@@ -203,8 +203,6 @@ module ActiveRecord::Import::PostgreSQLAdapter
203
203
  true
204
204
  end
205
205
 
206
- private
207
-
208
206
  def database_version
209
207
  defined?(postgresql_version) ? postgresql_version : super
210
208
  end
@@ -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
- import_associations(models, options.dup.merge(validate: false)) if options[:recursive]
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
- association_primary_key = association_reflection.association_primary_key
919
- model.public_send("#{column_name}=", association.send(association_primary_key))
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 and :returning not supported for associations
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
- timestamp = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
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.send :clear_association_cache
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
 
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Import
3
- VERSION = "1.2.0".freeze
3
+ VERSION = "1.3.0".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,6 @@
1
+ class Customer < ActiveRecord::Base
2
+ has_many :orders,
3
+ inverse_of: :customer,
4
+ primary_key: %i(account_id id),
5
+ foreign_key: %i(account_id customer_id)
6
+ end
@@ -0,0 +1,6 @@
1
+ class Order < ActiveRecord::Base
2
+ belongs_to :customer,
3
+ inverse_of: :orders,
4
+ primary_key: %i(account_id id),
5
+ foreign_key: %i(account_id customer_id)
6
+ end
@@ -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.2.0
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-07-17 00:00:00.000000000 Z
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: '3.2'
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: '3.2'
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.0.0
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.9
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
@@ -1,2 +0,0 @@
1
- gem 'activerecord', '~> 3.2.0'
2
- gem 'composite_primary_keys', '~> 5.0'
data/gemfiles/4.0.gemfile DELETED
@@ -1,2 +0,0 @@
1
- gem 'activerecord', '~> 4.0.0'
2
- gem 'composite_primary_keys', '~> 6.0'
data/gemfiles/4.1.gemfile DELETED
@@ -1,2 +0,0 @@
1
- gem 'activerecord', '~> 4.1.0'
2
- gem 'composite_primary_keys', '~> 7.0'