activerecord-import 0.22.0 → 0.23.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
  SHA1:
3
- metadata.gz: 89358f97c9fd1550a1d32d572db5f126d41b6b9c
4
- data.tar.gz: e840ba026216f3e0bc60a91b52bb207a558324d0
3
+ metadata.gz: 25b9f077b6e370081a1c29b59ba3ce50be68659c
4
+ data.tar.gz: adc5eff35697da10f5a6e3922980dfdd3ea849a6
5
5
  SHA512:
6
- metadata.gz: de20a46627950ac06773a6b8215b5dd134a3dc0f574407e9980c69dcc45a19b08db80aee089812b83be356913bf8f343737fec8166a0a77356e5fb546ec80e8b
7
- data.tar.gz: d1de87a630f697453cfbba9cb83e64b061c157a7d65affc271bfced0e4088afbc0870dcba0dfbc2c2ca1bc8854b137abcb0e8114de0471acb823ba9692df8f1c
6
+ metadata.gz: c8211cc8ed17997e92e944c1d36533ce501d18401da25df549e700fdd37e4223f5bcef2a342b3c8aa74af31d23d16c932a6e39b2445dba83dc8866575da16196
7
+ data.tar.gz: 293a3eb933956824ec0fd0b9dfe760ba43d262b3154a5286f3cb33d677ae0c2949effd9c92006dbaa97f5748d97b289bd2483c5b68933ca8e2d8698c18d26111
@@ -14,6 +14,7 @@ env:
14
14
  - AR_VERSION=4.2
15
15
  - AR_VERSION=5.0
16
16
  - AR_VERSION=5.1
17
+ - AR_VERSION=5.2
17
18
 
18
19
  matrix:
19
20
  include:
@@ -1,3 +1,17 @@
1
+ ## Changes in 0.23.0
2
+
3
+ ### New Features
4
+
5
+ * Rename `import` method to `bulk_import and alias to `import`. Thanks
6
+ to @itay-grudev, @jkowens via \#498.
7
+ * Increment lock_version on duplicate key update. Thanks to @aimerald
8
+ via \#400.
9
+
10
+ ### Fixes
11
+
12
+ * Fix import_without_validations_or_callbacks exception if array is empty.
13
+ Thanks to @doloopwhile via \#508.
14
+
1
15
  ## Changes in 0.22.0
2
16
 
3
17
  ### New Features
@@ -7,7 +21,9 @@
7
21
 
8
22
  ### Fixes
9
23
 
10
- * Fix validation logic for recursive import. Thanks to @eric-simonton-sama, @jkowens via
24
+ * Fix validation logic for recursive import. For those on Rails 5.0 and 5.1,
25
+ this change requires models with polymorphic associations to specify the `inverse_of`
26
+ argument (See issue #495). Thanks to @eric-simonton-sama, @jkowens via
11
27
  \#489.
12
28
 
13
29
  ## Changes in 0.21.0
data/Gemfile CHANGED
@@ -2,6 +2,11 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ version = ENV['AR_VERSION'].to_f
6
+
7
+ mysql2_version = '0.3.0'
8
+ mysql2_version = '0.4.0' if version >= 4.2
9
+
5
10
  group :development, :test do
6
11
  gem 'rubocop', '~> 0.40.0'
7
12
  gem 'rake'
@@ -9,7 +14,7 @@ end
9
14
 
10
15
  # Database Adapters
11
16
  platforms :ruby do
12
- gem "mysql2", "~> 0.3.0"
17
+ gem "mysql2", "~> #{mysql2_version}"
13
18
  gem "pg", "~> 0.9"
14
19
  gem "sqlite3", "~> 1.3.10"
15
20
  gem "seamless_database_pool", "~> 1.0.20"
@@ -27,7 +32,7 @@ end
27
32
  gem "factory_girl", "~> 4.2.0"
28
33
  gem "timecop"
29
34
  gem "chronic"
30
- gem "mocha"
35
+ gem "mocha", "~> 1.3.0"
31
36
 
32
37
  # Debugging
33
38
  platforms :jruby do
@@ -43,9 +48,7 @@ platforms :ruby do
43
48
  gem "rb-readline"
44
49
  end
45
50
 
46
- version = ENV['AR_VERSION'] || "4.2"
47
-
48
- if version >= "4.0"
51
+ if version >= 4.0
49
52
  gem "minitest"
50
53
  else
51
54
  gem "test-unit"
@@ -1,2 +1 @@
1
1
  gem 'activerecord', '~> 5.0.0'
2
- gem 'composite_primary_keys', '~> 9.0'
@@ -1,2 +1 @@
1
1
  gem 'activerecord', '~> 5.1.0'
2
- gem 'composite_primary_keys', '~> 10.0'
@@ -0,0 +1,2 @@
1
+ gem 'activerecord', '~> 5.2.0.rc1'
2
+ gem 'composite_primary_keys', '~> 11.0.0.rc2'
@@ -45,7 +45,7 @@ module ActiveRecord::Import::AbstractAdapter
45
45
  post_sql_statements = []
46
46
 
47
47
  if supports_on_duplicate_key_update? && options[:on_duplicate_key_update]
48
- post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update], options[:primary_key] )
48
+ post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update], options[:primary_key], options[:locking_column] )
49
49
  elsif options[:on_duplicate_key_update]
50
50
  logger.warn "Ignoring on_duplicate_key_update because it is not supported by the database."
51
51
  end
@@ -87,10 +87,11 @@ module ActiveRecord::Import::MysqlAdapter
87
87
  def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
88
88
  sql = ' ON DUPLICATE KEY UPDATE '
89
89
  arg = args.first
90
+ locking_column = args.last
90
91
  if arg.is_a?( Array )
91
- sql << sql_for_on_duplicate_key_update_as_array( table_name, arg )
92
+ sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arg )
92
93
  elsif arg.is_a?( Hash )
93
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, arg )
94
+ sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, arg )
94
95
  elsif arg.is_a?( String )
95
96
  sql << arg
96
97
  else
@@ -99,20 +100,22 @@ module ActiveRecord::Import::MysqlAdapter
99
100
  sql
100
101
  end
101
102
 
102
- def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
103
+ def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc:
103
104
  results = arr.map do |column|
104
105
  qc = quote_column_name( column )
105
106
  "#{table_name}.#{qc}=VALUES(#{qc})"
106
107
  end
108
+ increment_locking_column!(results, table_name, locking_column)
107
109
  results.join( ',' )
108
110
  end
109
111
 
110
- def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
112
+ def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc:
111
113
  results = hsh.map do |column1, column2|
112
114
  qc1 = quote_column_name( column1 )
113
115
  qc2 = quote_column_name( column2 )
114
116
  "#{table_name}.#{qc1}=VALUES( #{qc2} )"
115
117
  end
118
+ increment_locking_column!(results, table_name, locking_column)
116
119
  results.join( ',')
117
120
  end
118
121
 
@@ -120,4 +123,10 @@ module ActiveRecord::Import::MysqlAdapter
120
123
  def duplicate_key_update_error?(exception) # :nodoc:
121
124
  exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
122
125
  end
126
+
127
+ def increment_locking_column!(results, table_name, locking_column)
128
+ if locking_column.present?
129
+ results << "#{table_name}.`#{locking_column}`=`#{locking_column}`+1"
130
+ end
131
+ end
123
132
  end
@@ -119,7 +119,7 @@ module ActiveRecord::Import::PostgreSQLAdapter
119
119
  # Returns a generated ON CONFLICT DO UPDATE statement given the passed
120
120
  # in +args+.
121
121
  def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
122
- arg, primary_key = args
122
+ arg, primary_key, locking_column = args
123
123
  arg = { columns: arg } if arg.is_a?( Array ) || arg.is_a?( String )
124
124
  return unless arg.is_a?( Hash )
125
125
 
@@ -139,9 +139,9 @@ module ActiveRecord::Import::PostgreSQLAdapter
139
139
 
140
140
  sql << "#{conflict_target}DO UPDATE SET "
141
141
  if columns.is_a?( Array )
142
- sql << sql_for_on_duplicate_key_update_as_array( table_name, columns )
142
+ sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, columns )
143
143
  elsif columns.is_a?( Hash )
144
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, columns )
144
+ sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, columns )
145
145
  elsif columns.is_a?( String )
146
146
  sql << columns
147
147
  else
@@ -153,20 +153,22 @@ module ActiveRecord::Import::PostgreSQLAdapter
153
153
  sql
154
154
  end
155
155
 
156
- def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
156
+ def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc:
157
157
  results = arr.map do |column|
158
158
  qc = quote_column_name( column )
159
159
  "#{qc}=EXCLUDED.#{qc}"
160
160
  end
161
+ increment_locking_column!(results, locking_column)
161
162
  results.join( ',' )
162
163
  end
163
164
 
164
- def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
165
+ def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc:
165
166
  results = hsh.map do |column1, column2|
166
167
  qc1 = quote_column_name( column1 )
167
168
  qc2 = quote_column_name( column2 )
168
169
  "#{qc1}=EXCLUDED.#{qc2}"
169
170
  end
171
+ increment_locking_column!(results, locking_column)
170
172
  results.join( ',' )
171
173
  end
172
174
 
@@ -200,4 +202,10 @@ module ActiveRecord::Import::PostgreSQLAdapter
200
202
  def supports_setting_primary_key_of_imported_objects?
201
203
  true
202
204
  end
205
+
206
+ def increment_locking_column!(results, locking_column)
207
+ if locking_column.present?
208
+ results << "\"#{locking_column}\"=EXCLUDED.\"#{locking_column}\"+1"
209
+ end
210
+ end
203
211
  end
@@ -79,13 +79,14 @@ module ActiveRecord::Import #:nodoc:
79
79
  end
80
80
 
81
81
  class ActiveRecord::Associations::CollectionProxy
82
- def import(*args, &block)
83
- @association.import(*args, &block)
82
+ def bulk_import(*args, &block)
83
+ @association.bulk_import(*args, &block)
84
84
  end
85
+ alias import bulk_import unless respond_to? :import
85
86
  end
86
87
 
87
88
  class ActiveRecord::Associations::CollectionAssociation
88
- def import(*args, &block)
89
+ def bulk_import(*args, &block)
89
90
  unless owner.persisted?
90
91
  raise ActiveRecord::RecordNotSaved, "You cannot call import unless the parent is saved"
91
92
  end
@@ -118,7 +119,7 @@ class ActiveRecord::Associations::CollectionAssociation
118
119
  m.public_send "#{reflection.type}=", owner.class.name if reflection.type
119
120
  end
120
121
 
121
- return model_klass.import column_names, models, options
122
+ return model_klass.bulk_import column_names, models, options
122
123
 
123
124
  # supports array of hash objects
124
125
  elsif args.last.is_a?( Array ) && args.last.first.is_a?(Hash)
@@ -157,7 +158,7 @@ class ActiveRecord::Associations::CollectionAssociation
157
158
  end
158
159
  end
159
160
 
160
- return model_klass.import column_names, array_of_attributes, options
161
+ return model_klass.bulk_import column_names, array_of_attributes, options
161
162
 
162
163
  # supports empty array
163
164
  elsif args.last.is_a?( Array ) && args.last.empty?
@@ -192,11 +193,12 @@ class ActiveRecord::Associations::CollectionAssociation
192
193
  end
193
194
  end
194
195
 
195
- return model_klass.import column_names, array_of_attributes, options
196
+ return model_klass.bulk_import column_names, array_of_attributes, options
196
197
  else
197
198
  raise ArgumentError, "Invalid arguments!"
198
199
  end
199
200
  end
201
+ alias import bulk_import unless respond_to? :import
200
202
  end
201
203
 
202
204
  class ActiveRecord::Base
@@ -447,7 +449,7 @@ class ActiveRecord::Base
447
449
  # * num_inserts - the number of insert statements it took to import the data
448
450
  # * ids - the primary keys of the imported ids if the adapter supports it, otherwise an empty array.
449
451
  # * results - import results if the adapter supports it, otherwise an empty array.
450
- def import(*args)
452
+ def bulk_import(*args)
451
453
  if args.first.is_a?( Array ) && args.first.first.is_a?(ActiveRecord::Base)
452
454
  options = {}
453
455
  options.merge!( args.pop ) if args.last.is_a?(Hash)
@@ -458,23 +460,26 @@ class ActiveRecord::Base
458
460
  import_helper(*args)
459
461
  end
460
462
  end
463
+ alias import bulk_import unless respond_to? :import
461
464
 
462
465
  # Imports a collection of values if all values are valid. Import fails at the
463
466
  # first encountered validation error and raises ActiveRecord::RecordInvalid
464
467
  # with the failed instance.
465
- def import!(*args)
468
+ def bulk_import!(*args)
466
469
  options = args.last.is_a?( Hash ) ? args.pop : {}
467
470
  options[:validate] = true
468
471
  options[:raise_error] = true
469
472
 
470
- import(*args, options)
473
+ bulk_import(*args, options)
471
474
  end
475
+ alias import! bulk_import! unless respond_to? :import!
472
476
 
473
477
  def import_helper( *args )
474
478
  options = { validate: true, timestamps: true }
475
479
  options.merge!( args.pop ) if args.last.is_a? Hash
476
480
  # making sure that current model's primary key is used
477
481
  options[:primary_key] = primary_key
482
+ options[:locking_column] = locking_column if attribute_names.include?(locking_column)
478
483
 
479
484
  # Don't modify incoming arguments
480
485
  on_duplicate_key_update = options[:on_duplicate_key_update]
@@ -656,7 +661,7 @@ class ActiveRecord::Base
656
661
 
657
662
  array_of_attributes.compact!
658
663
 
659
- result = if array_of_attributes.empty? || options[:all_or_none] && failed_instances.any?
664
+ result = if options[:all_or_none] && failed_instances.any?
660
665
  ActiveRecord::Import::Result.new([], 0, [], [])
661
666
  else
662
667
  import_without_validations_or_callbacks( column_names, array_of_attributes, options )
@@ -671,6 +676,8 @@ class ActiveRecord::Base
671
676
  # information on +column_names+, +array_of_attributes_ and
672
677
  # +options+.
673
678
  def import_without_validations_or_callbacks( column_names, array_of_attributes, options = {} )
679
+ return ActiveRecord::Import::Result.new([], 0, [], []) if array_of_attributes.empty?
680
+
674
681
  column_names = column_names.map(&:to_sym)
675
682
  scope_columns, scope_values = scope_attributes.to_a.transpose
676
683
 
@@ -802,7 +809,7 @@ class ActiveRecord::Base
802
809
 
803
810
  associated_objects_by_class.each_value do |associations|
804
811
  associations.each_value do |associated_records|
805
- associated_records.first.class.import(associated_records, options) unless associated_records.empty?
812
+ associated_records.first.class.bulk_import(associated_records, options) unless associated_records.empty?
806
813
  end
807
814
  end
808
815
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Import
3
- VERSION = "0.22.0".freeze
3
+ VERSION = "0.23.0".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,3 @@
1
+ class Account < ActiveRecord::Base
2
+ self.locking_column = :lock
3
+ end
@@ -0,0 +1,7 @@
1
+ module Bike
2
+ def self.table_name_prefix
3
+ 'bike_'
4
+ end
5
+ class Maker < ActiveRecord::Base
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ class User < ActiveRecord::Base; end
@@ -159,6 +159,21 @@ ActiveRecord::Schema.define do
159
159
  t.string :Features
160
160
  end
161
161
 
162
+ create_table :users, force: :cascade do |t|
163
+ t.string :name, null: false
164
+ t.integer :lock_version, null: false, default: 0
165
+ end
166
+
167
+ create_table :accounts, force: :cascade do |t|
168
+ t.string :name, null: false
169
+ t.integer :lock, null: false, default: 0
170
+ end
171
+
172
+ create_table :bike_makers, force: :cascade do |t|
173
+ t.string :name, null: false
174
+ t.integer :lock_version, null: false, default: 0
175
+ end
176
+
162
177
  add_index :cars, :Name, unique: true
163
178
 
164
179
  unless ENV["SKIP_COMPOSITE_PK"]
@@ -5,6 +5,213 @@ def should_support_basic_on_duplicate_key_update
5
5
  macro(:perform_import) { raise "supply your own #perform_import in a context below" }
6
6
  macro(:updated_topic) { Topic.find(@topic.id) }
7
7
 
8
+ context "with lock_version upsert" do
9
+ describe 'optimistic lock' do
10
+ it 'lock_version upsert after on_duplcate_key_update by model' do
11
+ users = [
12
+ User.new(name: 'Salomon'),
13
+ User.new(name: 'Nathan')
14
+ ]
15
+ User.import(users)
16
+ assert User.count == users.length
17
+ User.all.each do |user|
18
+ assert_equal 0, user.lock_version
19
+ end
20
+ updated_users = User.all.map do |user|
21
+ user.name += ' Rothschild'
22
+ user
23
+ end
24
+ User.import(updated_users, on_duplicate_key_update: [:name])
25
+ assert User.count == updated_users.length
26
+ User.all.each_with_index do |user, i|
27
+ assert_equal user.name, users[i].name + ' Rothschild'
28
+ assert_equal 1, user.lock_version
29
+ end
30
+ end
31
+
32
+ it 'lock_version upsert after on_duplcate_key_update by array' do
33
+ users = [
34
+ User.new(name: 'Salomon'),
35
+ User.new(name: 'Nathan')
36
+ ]
37
+ User.import(users)
38
+ assert User.count == users.length
39
+ User.all.each do |user|
40
+ assert_equal 0, user.lock_version
41
+ end
42
+
43
+ columns = [:id, :name]
44
+ updated_values = User.all.map do |user|
45
+ user.name += ' Rothschild'
46
+ [user.id, user.name]
47
+ end
48
+ User.import(columns, updated_values, on_duplicate_key_update: [:name])
49
+ assert User.count == updated_values.length
50
+ User.all.each_with_index do |user, i|
51
+ assert_equal user.name, users[i].name + ' Rothschild'
52
+ assert_equal 1, user.lock_version
53
+ end
54
+ end
55
+
56
+ it 'lock_version upsert after on_duplcate_key_update by hash' do
57
+ users = [
58
+ User.new(name: 'Salomon'),
59
+ User.new(name: 'Nathan')
60
+ ]
61
+ User.import(users)
62
+ assert User.count == users.length
63
+ User.all.each do |user|
64
+ assert_equal 0, user.lock_version
65
+ end
66
+ updated_values = User.all.map do |user|
67
+ user.name += ' Rothschild'
68
+ { id: user.id, name: user.name }
69
+ end
70
+ User.import(updated_values, on_duplicate_key_update: [:name])
71
+ assert User.count == updated_values.length
72
+ User.all.each_with_index do |user, i|
73
+ assert_equal user.name, users[i].name + ' Rothschild'
74
+ assert_equal 1, user.lock_version
75
+ end
76
+ end
77
+
78
+ it 'upsert optimistic lock columns other than lock_version by model' do
79
+ accounts = [
80
+ Account.new(name: 'Salomon'),
81
+ Account.new(name: 'Nathan')
82
+ ]
83
+ Account.import(accounts)
84
+ assert Account.count == accounts.length
85
+ Account.all.each do |user|
86
+ assert_equal 0, user.lock
87
+ end
88
+ updated_accounts = Account.all.map do |user|
89
+ user.name += ' Rothschild'
90
+ user
91
+ end
92
+ Account.import(updated_accounts, on_duplicate_key_update: [:id, :name])
93
+ assert Account.count == updated_accounts.length
94
+ Account.all.each_with_index do |user, i|
95
+ assert_equal user.name, accounts[i].name + ' Rothschild'
96
+ assert_equal 1, user.lock
97
+ end
98
+ end
99
+
100
+ it 'upsert optimistic lock columns other than lock_version by array' do
101
+ accounts = [
102
+ Account.new(name: 'Salomon'),
103
+ Account.new(name: 'Nathan')
104
+ ]
105
+ Account.import(accounts)
106
+ assert Account.count == accounts.length
107
+ Account.all.each do |user|
108
+ assert_equal 0, user.lock
109
+ end
110
+
111
+ columns = [:id, :name]
112
+ updated_values = Account.all.map do |user|
113
+ user.name += ' Rothschild'
114
+ [user.id, user.name]
115
+ end
116
+ Account.import(columns, updated_values, on_duplicate_key_update: [:name])
117
+ assert Account.count == updated_values.length
118
+ Account.all.each_with_index do |user, i|
119
+ assert_equal user.name, accounts[i].name + ' Rothschild'
120
+ assert_equal 1, user.lock
121
+ end
122
+ end
123
+
124
+ it 'upsert optimistic lock columns other than lock_version by hash' do
125
+ accounts = [
126
+ Account.new(name: 'Salomon'),
127
+ Account.new(name: 'Nathan')
128
+ ]
129
+ Account.import(accounts)
130
+ assert Account.count == accounts.length
131
+ Account.all.each do |user|
132
+ assert_equal 0, user.lock
133
+ end
134
+ updated_values = Account.all.map do |user|
135
+ user.name += ' Rothschild'
136
+ { id: user.id, name: user.name }
137
+ end
138
+ Account.import(updated_values, on_duplicate_key_update: [:name])
139
+ assert Account.count == updated_values.length
140
+ Account.all.each_with_index do |user, i|
141
+ assert_equal user.name, accounts[i].name + ' Rothschild'
142
+ assert_equal 1, user.lock
143
+ end
144
+ end
145
+
146
+ it 'update the lock_version of models separated by namespaces by model' do
147
+ makers = [
148
+ Bike::Maker.new(name: 'Yamaha'),
149
+ Bike::Maker.new(name: 'Honda')
150
+ ]
151
+ Bike::Maker.import(makers)
152
+ assert Bike::Maker.count == makers.length
153
+ Bike::Maker.all.each do |maker|
154
+ assert_equal 0, maker.lock_version
155
+ end
156
+ updated_makers = Bike::Maker.all.map do |maker|
157
+ maker.name += ' bikes'
158
+ maker
159
+ end
160
+ Bike::Maker.import(updated_makers, on_duplicate_key_update: [:name])
161
+ assert Bike::Maker.count == updated_makers.length
162
+ Bike::Maker.all.each_with_index do |maker, i|
163
+ assert_equal maker.name, makers[i].name + ' bikes'
164
+ assert_equal 1, maker.lock_version
165
+ end
166
+ end
167
+ it 'update the lock_version of models separated by namespaces by array' do
168
+ makers = [
169
+ Bike::Maker.new(name: 'Yamaha'),
170
+ Bike::Maker.new(name: 'Honda')
171
+ ]
172
+ Bike::Maker.import(makers)
173
+ assert Bike::Maker.count == makers.length
174
+ Bike::Maker.all.each do |maker|
175
+ assert_equal 0, maker.lock_version
176
+ end
177
+
178
+ columns = [:id, :name]
179
+ updated_values = Bike::Maker.all.map do |maker|
180
+ maker.name += ' bikes'
181
+ [maker.id, maker.name]
182
+ end
183
+ Bike::Maker.import(columns, updated_values, on_duplicate_key_update: [:name])
184
+ assert Bike::Maker.count == updated_values.length
185
+ Bike::Maker.all.each_with_index do |maker, i|
186
+ assert_equal maker.name, makers[i].name + ' bikes'
187
+ assert_equal 1, maker.lock_version
188
+ end
189
+ end
190
+
191
+ it 'update the lock_version of models separated by namespaces by hash' do
192
+ makers = [
193
+ Bike::Maker.new(name: 'Yamaha'),
194
+ Bike::Maker.new(name: 'Honda')
195
+ ]
196
+ Bike::Maker.import(makers)
197
+ assert Bike::Maker.count == makers.length
198
+ Bike::Maker.all.each do |maker|
199
+ assert_equal 0, maker.lock_version
200
+ end
201
+ updated_values = Bike::Maker.all.map do |maker|
202
+ maker.name += ' bikes'
203
+ { id: maker.id, name: maker.name }
204
+ end
205
+ Bike::Maker.import(updated_values, on_duplicate_key_update: [:name])
206
+ assert Bike::Maker.count == updated_values.length
207
+ Bike::Maker.all.each_with_index do |maker, i|
208
+ assert_equal maker.name, makers[i].name + ' bikes'
209
+ assert_equal 1, maker.lock_version
210
+ end
211
+ end
212
+ end
213
+ end
214
+
8
215
  context "with :on_duplicate_key_update" do
9
216
  describe "argument safety" do
10
217
  it "should not modify the passed in :on_duplicate_key_update array" do
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: 0.22.0
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Dennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-22 00:00:00.000000000 Z
11
+ date: 2018-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -74,6 +74,7 @@ files:
74
74
  - gemfiles/4.2.gemfile
75
75
  - gemfiles/5.0.gemfile
76
76
  - gemfiles/5.1.gemfile
77
+ - gemfiles/5.2.gemfile
77
78
  - lib/activerecord-import.rb
78
79
  - lib/activerecord-import/active_record/adapters/abstract_adapter.rb
79
80
  - lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb
@@ -114,7 +115,9 @@ files:
114
115
  - test/jdbcmysql/import_test.rb
115
116
  - test/jdbcpostgresql/import_test.rb
116
117
  - test/jdbcsqlite3/import_test.rb
118
+ - test/models/account.rb
117
119
  - test/models/alarm.rb
120
+ - test/models/bike_maker.rb
118
121
  - test/models/book.rb
119
122
  - test/models/car.rb
120
123
  - test/models/chapter.rb
@@ -127,6 +130,7 @@ files:
127
130
  - test/models/rule.rb
128
131
  - test/models/tag.rb
129
132
  - test/models/topic.rb
133
+ - test/models/user.rb
130
134
  - test/models/vendor.rb
131
135
  - test/models/widget.rb
132
136
  - test/mysql2/import_test.rb
@@ -198,7 +202,9 @@ test_files:
198
202
  - test/jdbcmysql/import_test.rb
199
203
  - test/jdbcpostgresql/import_test.rb
200
204
  - test/jdbcsqlite3/import_test.rb
205
+ - test/models/account.rb
201
206
  - test/models/alarm.rb
207
+ - test/models/bike_maker.rb
202
208
  - test/models/book.rb
203
209
  - test/models/car.rb
204
210
  - test/models/chapter.rb
@@ -211,6 +217,7 @@ test_files:
211
217
  - test/models/rule.rb
212
218
  - test/models/tag.rb
213
219
  - test/models/topic.rb
220
+ - test/models/user.rb
214
221
  - test/models/vendor.rb
215
222
  - test/models/widget.rb
216
223
  - test/mysql2/import_test.rb