activerecord-import 0.22.0 → 0.23.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
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