activerecord-import 2.2.0 → 2.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.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.markdown +9 -9
  4. data/lib/activerecord-import/active_record/adapters/mysql2_proxy_adapter.rb +8 -0
  5. data/lib/activerecord-import/active_record/adapters/postgresql_proxy_adapter.rb +8 -0
  6. data/lib/activerecord-import/active_record/adapters/sqlite3_proxy_adapter.rb +8 -0
  7. data/lib/activerecord-import/active_record/adapters/trilogy_proxy_adapter.rb +8 -0
  8. data/lib/activerecord-import/adapters/active_record_proxy_adapter.rb +19 -0
  9. data/lib/activerecord-import/adapters/mysql2_proxy_adapter.rb +9 -0
  10. data/lib/activerecord-import/adapters/mysql_adapter.rb +10 -3
  11. data/lib/activerecord-import/adapters/postgresql_adapter.rb +1 -1
  12. data/lib/activerecord-import/adapters/postgresql_proxy_adapter.rb +9 -0
  13. data/lib/activerecord-import/adapters/sqlite3_proxy_adapter.rb +9 -0
  14. data/lib/activerecord-import/adapters/trilogy_proxy_adapter.rb +9 -0
  15. data/lib/activerecord-import/base.rb +0 -2
  16. data/lib/activerecord-import/import.rb +243 -207
  17. data/lib/activerecord-import/version.rb +1 -1
  18. metadata +13 -208
  19. data/.github/workflows/test.yaml +0 -165
  20. data/.gitignore +0 -37
  21. data/.rubocop.yml +0 -118
  22. data/.rubocop_todo.yml +0 -30
  23. data/Brewfile +0 -5
  24. data/Dockerfile +0 -23
  25. data/Gemfile +0 -63
  26. data/Rakefile +0 -75
  27. data/activerecord-import.gemspec +0 -28
  28. data/benchmarks/README +0 -32
  29. data/benchmarks/benchmark.rb +0 -72
  30. data/benchmarks/lib/base.rb +0 -143
  31. data/benchmarks/lib/cli_parser.rb +0 -111
  32. data/benchmarks/lib/float.rb +0 -17
  33. data/benchmarks/lib/mysql2_benchmark.rb +0 -21
  34. data/benchmarks/lib/output_to_csv.rb +0 -21
  35. data/benchmarks/lib/output_to_html.rb +0 -66
  36. data/benchmarks/models/test_innodb.rb +0 -5
  37. data/benchmarks/models/test_memory.rb +0 -5
  38. data/benchmarks/models/test_myisam.rb +0 -5
  39. data/benchmarks/schema/mysql2_schema.rb +0 -18
  40. data/docker-compose.yml +0 -34
  41. data/gemfiles/5.2.gemfile +0 -4
  42. data/gemfiles/6.0.gemfile +0 -4
  43. data/gemfiles/6.1.gemfile +0 -4
  44. data/gemfiles/7.0.gemfile +0 -4
  45. data/gemfiles/7.1.gemfile +0 -3
  46. data/gemfiles/7.2.gemfile +0 -3
  47. data/gemfiles/8.0.gemfile +0 -3
  48. data/test/adapters/janus_mysql2.rb +0 -3
  49. data/test/adapters/janus_trilogy.rb +0 -11
  50. data/test/adapters/jdbcmysql.rb +0 -3
  51. data/test/adapters/jdbcpostgresql.rb +0 -3
  52. data/test/adapters/jdbcsqlite3.rb +0 -3
  53. data/test/adapters/makara_postgis.rb +0 -3
  54. data/test/adapters/mysql2.rb +0 -3
  55. data/test/adapters/mysql2_makara.rb +0 -3
  56. data/test/adapters/mysql2_proxy.rb +0 -3
  57. data/test/adapters/mysql2spatial.rb +0 -3
  58. data/test/adapters/postgis.rb +0 -3
  59. data/test/adapters/postgresql.rb +0 -3
  60. data/test/adapters/postgresql_makara.rb +0 -3
  61. data/test/adapters/postgresql_proxy.rb +0 -3
  62. data/test/adapters/seamless_database_pool.rb +0 -3
  63. data/test/adapters/spatialite.rb +0 -3
  64. data/test/adapters/sqlite3.rb +0 -3
  65. data/test/adapters/trilogy.rb +0 -11
  66. data/test/database.yml.sample +0 -73
  67. data/test/github/database.yml +0 -85
  68. data/test/import_test.rb +0 -970
  69. data/test/janus_mysql2/import_test.rb +0 -8
  70. data/test/janus_trilogy/import_test.rb +0 -7
  71. data/test/jdbcmysql/import_test.rb +0 -7
  72. data/test/jdbcpostgresql/import_test.rb +0 -6
  73. data/test/jdbcsqlite3/import_test.rb +0 -6
  74. data/test/makara_postgis/import_test.rb +0 -10
  75. data/test/models/account.rb +0 -5
  76. data/test/models/alarm.rb +0 -4
  77. data/test/models/animal.rb +0 -8
  78. data/test/models/author.rb +0 -9
  79. data/test/models/bike_maker.rb +0 -10
  80. data/test/models/book.rb +0 -18
  81. data/test/models/car.rb +0 -5
  82. data/test/models/card.rb +0 -5
  83. data/test/models/chapter.rb +0 -6
  84. data/test/models/composite_book.rb +0 -19
  85. data/test/models/composite_chapter.rb +0 -12
  86. data/test/models/customer.rb +0 -18
  87. data/test/models/deck.rb +0 -8
  88. data/test/models/dictionary.rb +0 -6
  89. data/test/models/discount.rb +0 -5
  90. data/test/models/end_note.rb +0 -6
  91. data/test/models/group.rb +0 -5
  92. data/test/models/order.rb +0 -17
  93. data/test/models/playing_card.rb +0 -4
  94. data/test/models/promotion.rb +0 -5
  95. data/test/models/question.rb +0 -5
  96. data/test/models/rule.rb +0 -5
  97. data/test/models/tag.rb +0 -12
  98. data/test/models/tag_alias.rb +0 -11
  99. data/test/models/topic.rb +0 -31
  100. data/test/models/user.rb +0 -5
  101. data/test/models/user_token.rb +0 -6
  102. data/test/models/vendor.rb +0 -9
  103. data/test/models/widget.rb +0 -33
  104. data/test/mysql2/import_test.rb +0 -7
  105. data/test/mysql2_makara/import_test.rb +0 -8
  106. data/test/mysql2_proxy/import_test.rb +0 -6
  107. data/test/mysqlspatial2/import_test.rb +0 -8
  108. data/test/postgis/import_test.rb +0 -10
  109. data/test/postgresql/import_test.rb +0 -6
  110. data/test/postgresql_proxy/import_test.rb +0 -6
  111. data/test/schema/generic_schema.rb +0 -230
  112. data/test/schema/jdbcpostgresql_schema.rb +0 -3
  113. data/test/schema/mysql2_schema.rb +0 -21
  114. data/test/schema/postgis_schema.rb +0 -3
  115. data/test/schema/postgresql_schema.rb +0 -94
  116. data/test/schema/sqlite3_schema.rb +0 -15
  117. data/test/schema/version.rb +0 -12
  118. data/test/sqlite3/import_test.rb +0 -6
  119. data/test/support/active_support/test_case_extensions.rb +0 -73
  120. data/test/support/assertions.rb +0 -75
  121. data/test/support/factories.rb +0 -66
  122. data/test/support/generate.rb +0 -31
  123. data/test/support/mysql/import_examples.rb +0 -97
  124. data/test/support/postgresql/import_examples.rb +0 -642
  125. data/test/support/shared_examples/on_duplicate_key_ignore.rb +0 -45
  126. data/test/support/shared_examples/on_duplicate_key_update.rb +0 -437
  127. data/test/support/shared_examples/recursive_import.rb +0 -352
  128. data/test/support/sqlite3/import_examples.rb +0 -232
  129. data/test/synchronize_test.rb +0 -43
  130. data/test/test_helper.rb +0 -91
  131. data/test/trilogy/import_test.rb +0 -7
  132. data/test/value_sets_bytes_parser_test.rb +0 -106
  133. data/test/value_sets_records_parser_test.rb +0 -34
@@ -1,437 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def should_support_basic_on_duplicate_key_update
4
- describe "#import" do
5
- extend ActiveSupport::TestCase::ImportAssertions
6
-
7
- macro(:perform_import) { raise "supply your own #perform_import in a context below" }
8
- macro(:updated_topic) { Topic.find(@topic.id) }
9
-
10
- context "with lock_version upsert" do
11
- describe 'optimistic lock' do
12
- it 'lock_version upsert after on_duplcate_key_update by model' do
13
- users = [
14
- User.new(name: 'Salomon'),
15
- User.new(name: 'Nathan')
16
- ]
17
- User.import(users)
18
- assert User.count == users.length
19
- User.all.each do |user|
20
- assert_equal 0, user.lock_version
21
- end
22
- updated_users = User.all.map do |user|
23
- user.name += ' Rothschild'
24
- user
25
- end
26
- User.import(updated_users, on_duplicate_key_update: [:name])
27
- assert User.count == updated_users.length
28
- User.all.each_with_index do |user, i|
29
- assert_equal user.name, "#{users[i].name} Rothschild"
30
- assert_equal 1, user.lock_version
31
- end
32
- end
33
-
34
- it 'lock_version upsert after on_duplcate_key_update by array' do
35
- users = [
36
- User.new(name: 'Salomon'),
37
- User.new(name: 'Nathan')
38
- ]
39
- User.import(users)
40
- assert User.count == users.length
41
- User.all.each do |user|
42
- assert_equal 0, user.lock_version
43
- end
44
-
45
- columns = [:id, :name]
46
- updated_values = User.all.map do |user|
47
- user.name += ' Rothschild'
48
- [user.id, user.name]
49
- end
50
- User.import(columns, updated_values, on_duplicate_key_update: [:name])
51
- assert User.count == updated_values.length
52
- User.all.each_with_index do |user, i|
53
- assert_equal user.name, "#{users[i].name} Rothschild"
54
- assert_equal 1, user.lock_version
55
- end
56
- end
57
-
58
- it 'lock_version upsert after on_duplcate_key_update by hash' do
59
- users = [
60
- User.new(name: 'Salomon'),
61
- User.new(name: 'Nathan')
62
- ]
63
- User.import(users)
64
- assert User.count == users.length
65
- User.all.each do |user|
66
- assert_equal 0, user.lock_version
67
- end
68
- updated_values = User.all.map do |user|
69
- user.name += ' Rothschild'
70
- { id: user.id, name: user.name }
71
- end
72
- User.import(updated_values, on_duplicate_key_update: [:name])
73
- assert User.count == updated_values.length
74
- User.all.each_with_index do |user, i|
75
- assert_equal user.name, "#{users[i].name} Rothschild"
76
- assert_equal 1, user.lock_version
77
- end
78
- updated_values2 = User.all.map do |user|
79
- user.name += ' jr.'
80
- { id: user.id, name: user.name }
81
- end
82
- User.import(updated_values2, on_duplicate_key_update: [:name])
83
- assert User.count == updated_values2.length
84
- User.all.each_with_index do |user, i|
85
- assert_equal user.name, "#{users[i].name} Rothschild jr."
86
- assert_equal 2, user.lock_version
87
- end
88
- end
89
-
90
- it 'upsert optimistic lock columns other than lock_version by model' do
91
- accounts = [
92
- Account.new(name: 'Salomon'),
93
- Account.new(name: 'Nathan')
94
- ]
95
- Account.import(accounts)
96
- assert Account.count == accounts.length
97
- Account.all.each do |user|
98
- assert_equal 0, user.lock
99
- end
100
- updated_accounts = Account.all.map do |user|
101
- user.name += ' Rothschild'
102
- user
103
- end
104
- Account.import(updated_accounts, on_duplicate_key_update: [:id, :name])
105
- assert Account.count == updated_accounts.length
106
- Account.all.each_with_index do |user, i|
107
- assert_equal user.name, "#{accounts[i].name} Rothschild"
108
- assert_equal 1, user.lock
109
- end
110
- end
111
-
112
- it 'upsert optimistic lock columns other than lock_version by array' do
113
- accounts = [
114
- Account.new(name: 'Salomon'),
115
- Account.new(name: 'Nathan')
116
- ]
117
- Account.import(accounts)
118
- assert Account.count == accounts.length
119
- Account.all.each do |user|
120
- assert_equal 0, user.lock
121
- end
122
-
123
- columns = [:id, :name]
124
- updated_values = Account.all.map do |user|
125
- user.name += ' Rothschild'
126
- [user.id, user.name]
127
- end
128
- Account.import(columns, updated_values, on_duplicate_key_update: [:name])
129
- assert Account.count == updated_values.length
130
- Account.all.each_with_index do |user, i|
131
- assert_equal user.name, "#{accounts[i].name} Rothschild"
132
- assert_equal 1, user.lock
133
- end
134
- end
135
-
136
- it 'upsert optimistic lock columns other than lock_version by hash' do
137
- accounts = [
138
- Account.new(name: 'Salomon'),
139
- Account.new(name: 'Nathan')
140
- ]
141
- Account.import(accounts)
142
- assert Account.count == accounts.length
143
- Account.all.each do |user|
144
- assert_equal 0, user.lock
145
- end
146
- updated_values = Account.all.map do |user|
147
- user.name += ' Rothschild'
148
- { id: user.id, name: user.name }
149
- end
150
- Account.import(updated_values, on_duplicate_key_update: [:name])
151
- assert Account.count == updated_values.length
152
- Account.all.each_with_index do |user, i|
153
- assert_equal user.name, "#{accounts[i].name} Rothschild"
154
- assert_equal 1, user.lock
155
- end
156
- end
157
-
158
- it 'update the lock_version of models separated by namespaces by model' do
159
- makers = [
160
- Bike::Maker.new(name: 'Yamaha'),
161
- Bike::Maker.new(name: 'Honda')
162
- ]
163
- Bike::Maker.import(makers)
164
- assert Bike::Maker.count == makers.length
165
- Bike::Maker.all.each do |maker|
166
- assert_equal 0, maker.lock_version
167
- end
168
- updated_makers = Bike::Maker.all.map do |maker|
169
- maker.name += ' bikes'
170
- maker
171
- end
172
- Bike::Maker.import(updated_makers, on_duplicate_key_update: [:name])
173
- assert Bike::Maker.count == updated_makers.length
174
- Bike::Maker.all.each_with_index do |maker, i|
175
- assert_equal maker.name, "#{makers[i].name} bikes"
176
- assert_equal 1, maker.lock_version
177
- end
178
- end
179
-
180
- it 'update the lock_version of models separated by namespaces by array' do
181
- makers = [
182
- Bike::Maker.new(name: 'Yamaha'),
183
- Bike::Maker.new(name: 'Honda')
184
- ]
185
- Bike::Maker.import(makers)
186
- assert Bike::Maker.count == makers.length
187
- Bike::Maker.all.each do |maker|
188
- assert_equal 0, maker.lock_version
189
- end
190
-
191
- columns = [:id, :name]
192
- updated_values = Bike::Maker.all.map do |maker|
193
- maker.name += ' bikes'
194
- [maker.id, maker.name]
195
- end
196
- Bike::Maker.import(columns, updated_values, on_duplicate_key_update: [:name])
197
- assert Bike::Maker.count == updated_values.length
198
- Bike::Maker.all.each_with_index do |maker, i|
199
- assert_equal maker.name, "#{makers[i].name} bikes"
200
- assert_equal 1, maker.lock_version
201
- end
202
- end
203
-
204
- it 'update the lock_version of models separated by namespaces by hash' do
205
- makers = [
206
- Bike::Maker.new(name: 'Yamaha'),
207
- Bike::Maker.new(name: 'Honda')
208
- ]
209
- Bike::Maker.import(makers)
210
- assert Bike::Maker.count == makers.length
211
- Bike::Maker.all.each do |maker|
212
- assert_equal 0, maker.lock_version
213
- end
214
- updated_values = Bike::Maker.all.map do |maker|
215
- maker.name += ' bikes'
216
- { id: maker.id, name: maker.name }
217
- end
218
- Bike::Maker.import(updated_values, on_duplicate_key_update: [:name])
219
- assert Bike::Maker.count == updated_values.length
220
- Bike::Maker.all.each_with_index do |maker, i|
221
- assert_equal maker.name, "#{makers[i].name} bikes"
222
- assert_equal 1, maker.lock_version
223
- end
224
- end
225
- end
226
-
227
- context 'with locking disabled' do
228
- it 'does not update the lock_version' do
229
- users = [
230
- User.new(name: 'Salomon'),
231
- User.new(name: 'Nathan')
232
- ]
233
- User.import(users)
234
- assert User.count == users.length
235
- User.all.each do |user|
236
- assert_equal 0, user.lock_version
237
- end
238
- updated_users = User.all.map do |user|
239
- user.name += ' Rothschild'
240
- user
241
- end
242
-
243
- ActiveRecord::Base.lock_optimistically = false # Disable locking
244
- User.import(updated_users, on_duplicate_key_update: [:name])
245
- ActiveRecord::Base.lock_optimistically = true # Enable locking
246
-
247
- assert User.count == updated_users.length
248
- User.all.each_with_index do |user, i|
249
- assert_equal user.name, "#{users[i].name} Rothschild"
250
- assert_equal 0, user.lock_version
251
- end
252
- end
253
- end
254
- end
255
-
256
- context "with :on_duplicate_key_update" do
257
- describe 'using :all' do
258
- let(:columns) { %w( id title author_name author_email_address parent_id ) }
259
- let(:updated_values) { [[99, "Book - 2nd Edition", "Jane Doe", "janedoe@example.com", 57]] }
260
-
261
- macro(:perform_import) do |*opts|
262
- Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: :all, validate: false)
263
- end
264
-
265
- setup do
266
- values = [[99, "Book", "John Doe", "john@doe.com", 17, 3]]
267
- Topic.import columns + ['replies_count'], values, validate: false
268
- end
269
-
270
- it 'updates all specified columns' do
271
- perform_import
272
- updated_topic = Topic.find(99)
273
- assert_equal 'Book - 2nd Edition', updated_topic.title
274
- assert_equal 'Jane Doe', updated_topic.author_name
275
- assert_equal 'janedoe@example.com', updated_topic.author_email_address
276
- assert_equal 57, updated_topic.parent_id
277
- assert_equal 3, updated_topic.replies_count
278
- end
279
- end
280
-
281
- describe "argument safety" do
282
- it "should not modify the passed in :on_duplicate_key_update array" do
283
- assert_nothing_raised do
284
- columns = %w(title author_name).freeze
285
- Topic.import columns, [%w(foo, bar)], on_duplicate_key_update: columns
286
- end
287
- end
288
- end
289
-
290
- context "with timestamps enabled" do
291
- let(:time) { Chronic.parse("5 minutes from now") }
292
-
293
- it 'should not overwrite changed updated_at with current timestamp' do
294
- topic = Topic.create(author_name: "Jane Doe", title: "Book")
295
- timestamp = Time.now.utc
296
- topic.updated_at = timestamp
297
- Topic.import [topic], on_duplicate_key_update: :all, validate: false
298
- assert_equal timestamp.to_s, Topic.last.updated_at.to_s
299
- end
300
-
301
- it 'should update updated_at with current timestamp' do
302
- topic = Topic.create(author_name: "Jane Doe", title: "Book")
303
- Timecop.freeze(time) do
304
- Topic.import [topic], on_duplicate_key_update: [:updated_at], validate: false
305
- assert_in_delta time.to_i, topic.reload.updated_at.to_i, 1.second
306
- end
307
- end
308
- end
309
-
310
- context "with validation checks turned off" do
311
- asssertion_group(:should_support_on_duplicate_key_update) do
312
- should_not_update_fields_not_mentioned
313
- should_update_foreign_keys
314
- should_not_update_created_at_on_timestamp_columns
315
- should_update_updated_at_on_timestamp_columns
316
- end
317
-
318
- let(:columns) { %w( id title author_name author_email_address parent_id ) }
319
- let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
320
- let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
321
-
322
- macro(:perform_import) do |*opts|
323
- Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
324
- end
325
-
326
- setup do
327
- Topic.import columns, values, validate: false
328
- @topic = Topic.find 99
329
- end
330
-
331
- context "using an empty array" do
332
- let(:update_columns) { [] }
333
- should_not_update_fields_not_mentioned
334
- should_update_updated_at_on_timestamp_columns
335
- end
336
-
337
- context "using string column names" do
338
- let(:update_columns) { %w(title author_email_address parent_id) }
339
- should_support_on_duplicate_key_update
340
- should_update_fields_mentioned
341
- end
342
-
343
- context "using symbol column names" do
344
- let(:update_columns) { [:title, :author_email_address, :parent_id] }
345
- should_support_on_duplicate_key_update
346
- should_update_fields_mentioned
347
- end
348
-
349
- context "using column aliases" do
350
- let(:columns) { %w( id title author_name author_email_address parent_id ) }
351
- let(:update_columns) { %w(title author_email_address parent_id) }
352
-
353
- context "with column aliases in column list" do
354
- let(:columns) { %w( id name author_name author_email_address parent_id ) }
355
- should_support_on_duplicate_key_update
356
- should_update_fields_mentioned
357
- end
358
-
359
- context "with column aliases in update columns list" do
360
- let(:update_columns) { %w(name author_email_address parent_id) }
361
- should_support_on_duplicate_key_update
362
- should_update_fields_mentioned
363
- end
364
- end
365
-
366
- if ENV['AR_VERSION'].to_i >= 6.0
367
- context "using ignored columns" do
368
- let(:columns) { %w( id title author_name author_email_address parent_id priority ) }
369
- let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17, 1]] }
370
- let(:update_columns) { %w(name author_email_address parent_id priority) }
371
- let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57, 2]] }
372
- should_support_on_duplicate_key_update
373
- should_update_fields_mentioned
374
- end
375
- end
376
- end
377
-
378
- context "with a table that has a non-standard primary key" do
379
- let(:columns) { [:promotion_id, :code] }
380
- let(:values) { [[1, 'DISCOUNT1']] }
381
- let(:updated_values) { [[1, 'DISCOUNT2']] }
382
- let(:update_columns) { [:code] }
383
-
384
- macro(:perform_import) do |*opts|
385
- Promotion.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
386
- end
387
- macro(:updated_promotion) { Promotion.find(@promotion.promotion_id) }
388
-
389
- setup do
390
- Promotion.import columns, values, validate: false
391
- @promotion = Promotion.find 1
392
- end
393
-
394
- it "should update specified columns" do
395
- perform_import
396
- assert_equal 'DISCOUNT2', updated_promotion.code
397
- end
398
- end
399
-
400
- unless ENV["SKIP_COMPOSITE_PK"]
401
- context "with composite primary keys" do
402
- it "should import array of values successfully" do
403
- columns = [:tag_id, :publisher_id, :tag]
404
- Tag.import columns, [[1, 1, 'Mystery']], validate: false
405
-
406
- assert_difference "Tag.count", +0 do
407
- Tag.import columns, [[1, 1, 'Science']], on_duplicate_key_update: [:tag], validate: false
408
- end
409
- assert_equal 'Science', Tag.first.tag
410
- end
411
- end
412
- end
413
- end
414
-
415
- context "with :on_duplicate_key_update turned off" do
416
- let(:columns) { %w( id title author_name author_email_address parent_id ) }
417
- let(:values) { [[100, "Book", "John Doe", "john@doe.com", 17]] }
418
- let(:updated_values) { [[100, "Book - 2nd Edition", "This should raise an exception", "john@nogo.com", 57]] }
419
-
420
- macro(:perform_import) do |*opts|
421
- # `on_duplicate_key_update: false` is the tested feature
422
- Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: false, validate: false)
423
- end
424
-
425
- setup do
426
- Topic.import columns, values, validate: false
427
- @topic = Topic.find 100
428
- end
429
-
430
- it "should raise ActiveRecord::RecordNotUnique" do
431
- assert_raise ActiveRecord::RecordNotUnique do
432
- perform_import
433
- end
434
- end
435
- end
436
- end
437
- end