activerecord-import 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +49 -0
  3. data/.rubocop_todo.yml +36 -0
  4. data/.travis.yml +31 -7
  5. data/CHANGELOG.md +19 -0
  6. data/Gemfile +5 -2
  7. data/README.markdown +6 -1
  8. data/Rakefile +5 -2
  9. data/activerecord-import.gemspec +1 -1
  10. data/benchmarks/benchmark.rb +67 -68
  11. data/benchmarks/lib/base.rb +136 -137
  12. data/benchmarks/lib/cli_parser.rb +106 -107
  13. data/benchmarks/lib/mysql2_benchmark.rb +19 -21
  14. data/benchmarks/lib/output_to_csv.rb +2 -1
  15. data/benchmarks/lib/output_to_html.rb +8 -13
  16. data/benchmarks/schema/mysql_schema.rb +8 -8
  17. data/gemfiles/4.0.gemfile +1 -1
  18. data/gemfiles/4.1.gemfile +1 -1
  19. data/gemfiles/4.2.gemfile +1 -1
  20. data/gemfiles/5.0.gemfile +1 -1
  21. data/lib/activerecord-import.rb +2 -0
  22. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
  23. data/lib/activerecord-import/adapters/abstract_adapter.rb +9 -9
  24. data/lib/activerecord-import/adapters/mysql_adapter.rb +17 -17
  25. data/lib/activerecord-import/adapters/postgresql_adapter.rb +20 -22
  26. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +9 -9
  27. data/lib/activerecord-import/base.rb +3 -3
  28. data/lib/activerecord-import/import.rb +152 -131
  29. data/lib/activerecord-import/synchronize.rb +20 -20
  30. data/lib/activerecord-import/value_sets_parser.rb +7 -6
  31. data/lib/activerecord-import/version.rb +1 -1
  32. data/test/adapters/mysql2spatial.rb +1 -1
  33. data/test/adapters/postgis.rb +1 -1
  34. data/test/adapters/postgresql.rb +1 -1
  35. data/test/adapters/spatialite.rb +1 -1
  36. data/test/adapters/sqlite3.rb +1 -1
  37. data/test/import_test.rb +121 -70
  38. data/test/models/book.rb +5 -6
  39. data/test/models/chapter.rb +2 -2
  40. data/test/models/discount.rb +3 -0
  41. data/test/models/end_note.rb +2 -2
  42. data/test/models/promotion.rb +1 -1
  43. data/test/models/question.rb +1 -1
  44. data/test/models/rule.rb +2 -2
  45. data/test/models/topic.rb +3 -3
  46. data/test/models/widget.rb +1 -1
  47. data/test/postgis/import_test.rb +1 -1
  48. data/test/schema/generic_schema.rb +100 -96
  49. data/test/schema/mysql_schema.rb +5 -7
  50. data/test/sqlite3/import_test.rb +0 -2
  51. data/test/support/active_support/test_case_extensions.rb +12 -15
  52. data/test/support/assertions.rb +1 -1
  53. data/test/support/factories.rb +15 -16
  54. data/test/support/generate.rb +4 -4
  55. data/test/support/mysql/import_examples.rb +21 -21
  56. data/test/support/postgresql/import_examples.rb +83 -55
  57. data/test/support/shared_examples/on_duplicate_key_update.rb +23 -23
  58. data/test/synchronize_test.rb +2 -2
  59. data/test/test_helper.rb +6 -8
  60. data/test/value_sets_bytes_parser_test.rb +14 -17
  61. data/test/value_sets_records_parser_test.rb +6 -6
  62. metadata +7 -4
  63. data/test/travis/build.sh +0 -34
@@ -1,11 +1,11 @@
1
1
  class ActiveSupport::TestCase
2
- def Build(*args)
2
+ def Build(*args) # rubocop:disable Style/MethodName
3
3
  n = args.shift if args.first.is_a?(Numeric)
4
4
  factory = args.shift
5
5
  factory_girl_args = args.shift || {}
6
6
 
7
7
  if n
8
- Array.new.tap do |collection|
8
+ [].tap do |collection|
9
9
  n.times.each { collection << FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args) }
10
10
  end
11
11
  else
@@ -13,13 +13,13 @@ class ActiveSupport::TestCase
13
13
  end
14
14
  end
15
15
 
16
- def Generate(*args)
16
+ def Generate(*args) # rubocop:disable Style/MethodName
17
17
  n = args.shift if args.first.is_a?(Numeric)
18
18
  factory = args.shift
19
19
  factory_girl_args = args.shift || {}
20
20
 
21
21
  if n
22
- Array.new.tap do |collection|
22
+ [].tap do |collection|
23
23
  n.times.each { collection << FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args) }
24
24
  end
25
25
  else
@@ -16,68 +16,68 @@ def should_support_mysql_import_functionality
16
16
  should_update_updated_at_on_timestamp_columns
17
17
  end
18
18
 
19
- macro(:perform_import){ raise "supply your own #perform_import in a context below" }
20
- macro(:updated_topic){ Topic.find(@topic.id) }
19
+ macro(:perform_import) { raise "supply your own #perform_import in a context below" }
20
+ macro(:updated_topic) { Topic.find(@topic.id) }
21
21
 
22
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
23
- let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
24
- let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
22
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
23
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
24
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
25
25
 
26
26
  macro(:perform_import) do |*opts|
27
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
27
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
28
28
  end
29
29
 
30
30
  setup do
31
- Topic.import columns, values, :validate => false
31
+ Topic.import columns, values, validate: false
32
32
  @topic = Topic.find 99
33
33
  end
34
34
 
35
35
  context "using string hash map" do
36
- let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
36
+ let(:update_columns) { { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
37
37
  should_support_on_duplicate_key_update
38
38
  should_update_fields_mentioned
39
39
  end
40
40
 
41
41
  context "using string hash map, but specifying column mismatches" do
42
- let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
42
+ let(:update_columns) { { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
43
43
  should_support_on_duplicate_key_update
44
44
  should_update_fields_mentioned_with_hash_mappings
45
45
  end
46
46
 
47
47
  context "using symbol hash map" do
48
- let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
48
+ let(:update_columns) { { title: :title, author_email_address: :author_email_address, parent_id: :parent_id } }
49
49
  should_support_on_duplicate_key_update
50
50
  should_update_fields_mentioned
51
51
  end
52
52
 
53
53
  context "using symbol hash map, but specifying column mismatches" do
54
- let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
54
+ let(:update_columns) { { title: :author_email_address, author_email_address: :title, parent_id: :parent_id } }
55
55
  should_support_on_duplicate_key_update
56
56
  should_update_fields_mentioned_with_hash_mappings
57
57
  end
58
58
  end
59
59
 
60
60
  context "with :synchronization option" do
61
- let(:topics){ Array.new }
62
- let(:values){ [ [topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"] ]}
63
- let(:columns){ %W(id author_name title) }
61
+ let(:topics) { [] }
62
+ let(:values) { [[topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"]] }
63
+ let(:columns) { %w(id author_name title) }
64
64
 
65
65
  setup do
66
- topics << Topic.create!(:title=>"LDAP", :author_name=>"Big Bird")
67
- topics << Topic.create!(:title=>"Rails Recipes", :author_name=>"Elmo")
66
+ topics << Topic.create!(title: "LDAP", author_name: "Big Bird")
67
+ topics << Topic.create!(title: "Rails Recipes", author_name: "Elmo")
68
68
  end
69
69
 
70
70
  it "synchronizes passed in ActiveRecord model instances with the data just imported" do
71
- columns2update = [ 'author_name' ]
71
+ columns2update = ['author_name']
72
72
 
73
73
  expected_count = Topic.count
74
74
  Topic.import( columns, values,
75
- :validate=>false,
76
- :on_duplicate_key_update=>columns2update,
77
- :synchronize=>topics )
75
+ validate: false,
76
+ on_duplicate_key_update: columns2update,
77
+ synchronize: topics )
78
78
 
79
79
  assert_equal expected_count, Topic.count, "no new records should have been created!"
80
- assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
80
+ assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
81
81
  assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
82
82
  end
83
83
  end
@@ -20,21 +20,21 @@ def should_support_postgresql_import_functionality
20
20
 
21
21
  describe "importing objects with associations" do
22
22
  let(:new_topics) { Build(num_topics, :topic_with_book) }
23
- let(:new_topics_with_invalid_chapter) {
24
- chapter = new_topics.first.books.first.chapters.first
25
- chapter.title = nil
26
- new_topics
27
- }
28
- let(:num_topics) {3}
29
- let(:num_books) {6}
30
- let(:num_chapters) {18}
31
- let(:num_endnotes) {24}
23
+ let(:new_topics_with_invalid_chapter) do
24
+ chapter = new_topics.first.books.first.chapters.first
25
+ chapter.title = nil
26
+ new_topics
27
+ end
28
+ let(:num_topics) { 3 }
29
+ let(:num_books) { 6 }
30
+ let(:num_chapters) { 18 }
31
+ let(:num_endnotes) { 24 }
32
32
 
33
33
  let(:new_question_with_rule) { FactoryGirl.build :question, :with_rule }
34
34
 
35
35
  it 'imports top level' do
36
36
  assert_difference "Topic.count", +num_topics do
37
- Topic.import new_topics, :recursive => true
37
+ Topic.import new_topics, recursive: true
38
38
  new_topics.each do |topic|
39
39
  assert_not_nil topic.id
40
40
  end
@@ -43,7 +43,7 @@ def should_support_postgresql_import_functionality
43
43
 
44
44
  it 'imports first level associations' do
45
45
  assert_difference "Book.count", +num_books do
46
- Topic.import new_topics, :recursive => true
46
+ Topic.import new_topics, recursive: true
47
47
  new_topics.each do |topic|
48
48
  topic.books.each do |book|
49
49
  assert_equal topic.id, book.topic_id
@@ -52,8 +52,23 @@ def should_support_postgresql_import_functionality
52
52
  end
53
53
  end
54
54
 
55
- [{:recursive => false}, {}].each do |import_options|
56
- it "skips recursion for #{import_options.to_s}" do
55
+ it 'imports polymorphic associations' do
56
+ discounts = Array.new(1) { |i| Discount.new(amount: i) }
57
+ books = Array.new(1) { |i| Book.new(author_name: "Author ##{i}", title: "Book ##{i}") }
58
+ books.each do |book|
59
+ book.discounts << discounts
60
+ end
61
+ Book.import books, recursive: true
62
+ books.each do |book|
63
+ book.discounts.each do |discount|
64
+ assert_not_nil discount.discountable_id
65
+ assert_equal 'Book', discount.discountable_type
66
+ end
67
+ end
68
+ end
69
+
70
+ [{ recursive: false }, {}].each do |import_options|
71
+ it "skips recursion for #{import_options}" do
57
72
  assert_difference "Book.count", 0 do
58
73
  Topic.import new_topics, import_options
59
74
  end
@@ -63,7 +78,7 @@ def should_support_postgresql_import_functionality
63
78
  it 'imports deeper nested associations' do
64
79
  assert_difference "Chapter.count", +num_chapters do
65
80
  assert_difference "EndNote.count", +num_endnotes do
66
- Topic.import new_topics, :recursive => true
81
+ Topic.import new_topics, recursive: true
67
82
  new_topics.each do |topic|
68
83
  topic.books.each do |book|
69
84
  book.chapters.each do |chapter|
@@ -80,7 +95,7 @@ def should_support_postgresql_import_functionality
80
95
 
81
96
  it "skips validation of the associations if requested" do
82
97
  assert_difference "Chapter.count", +num_chapters do
83
- Topic.import new_topics_with_invalid_chapter, :validate => false, :recursive => true
98
+ Topic.import new_topics_with_invalid_chapter, validate: false, recursive: true
84
99
  end
85
100
  end
86
101
 
@@ -95,15 +110,15 @@ def should_support_postgresql_import_functionality
95
110
  # being created, you would need to have validates_associated in your models and insert with validation
96
111
  describe "all_or_none" do
97
112
  [Book, Topic, EndNote].each do |type|
98
- it "creates #{type.to_s}" do
99
- assert_difference "#{type.to_s}.count", send("num_#{type.to_s.downcase}s") do
100
- Topic.import new_topics_with_invalid_chapter, :all_or_none => true, :recursive => true
113
+ it "creates #{type}" do
114
+ assert_difference "#{type}.count", send("num_#{type.to_s.downcase}s") do
115
+ Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
101
116
  end
102
117
  end
103
118
  end
104
119
  it "doesn't create chapters" do
105
120
  assert_difference "Chapter.count", 0 do
106
- Topic.import new_topics_with_invalid_chapter, :all_or_none => true, :recursive => true
121
+ Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
107
122
  end
108
123
  end
109
124
  end
@@ -141,35 +156,35 @@ def should_support_postgresql_upsert_functionality
141
156
  describe "#import" do
142
157
  extend ActiveSupport::TestCase::ImportAssertions
143
158
 
144
- macro(:perform_import){ raise "supply your own #perform_import in a context below" }
145
- macro(:updated_topic){ Topic.find(@topic.id) }
159
+ macro(:perform_import) { raise "supply your own #perform_import in a context below" }
160
+ macro(:updated_topic) { Topic.find(@topic.id) }
146
161
 
147
162
  context "with :on_duplicate_key_ignore and validation checks turned off" do
148
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
149
- let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
150
- let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
163
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
164
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
165
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
151
166
 
152
167
  macro(:perform_import) do |*opts|
153
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_ignore => value, :validate => false)
168
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_ignore: value, validate: false)
154
169
  end
155
170
 
156
171
  setup do
157
- Topic.import columns, values, :validate => false
172
+ Topic.import columns, values, validate: false
158
173
  @topic = Topic.find 99
159
174
  end
160
175
 
161
176
  context "using true" do
162
- let(:value){ true }
177
+ let(:value) { true }
163
178
  should_not_update_updated_at_on_timestamp_columns
164
179
  end
165
180
 
166
181
  context "using hash with :conflict_target" do
167
- let(:value){ { conflict_target: :id } }
182
+ let(:value) { { conflict_target: :id } }
168
183
  should_not_update_updated_at_on_timestamp_columns
169
184
  end
170
185
 
171
186
  context "using hash with :constraint_target" do
172
- let(:value){ { constraint_name: :topics_pkey } }
187
+ let(:value) { { constraint_name: :topics_pkey } }
173
188
  should_not_update_updated_at_on_timestamp_columns
174
189
  end
175
190
  end
@@ -184,101 +199,114 @@ def should_support_postgresql_upsert_functionality
184
199
 
185
200
  context "using a hash" do
186
201
  context "with :columns a hash" do
187
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
188
- let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
189
- let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
202
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
203
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
204
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
190
205
 
191
206
  macro(:perform_import) do |*opts|
192
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :conflict_target => :id, :columns => update_columns }, :validate => false)
207
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { conflict_target: :id, columns: update_columns }, validate: false)
193
208
  end
194
209
 
195
210
  setup do
196
- Topic.import columns, values, :validate => false
211
+ Topic.import columns, values, validate: false
197
212
  @topic = Topic.find 99
198
213
  end
199
214
 
200
215
  context "using string hash map" do
201
- let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
216
+ let(:update_columns) { { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
202
217
  should_support_on_duplicate_key_update
203
218
  should_update_fields_mentioned
204
219
  end
205
220
 
206
221
  context "using string hash map, but specifying column mismatches" do
207
- let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
222
+ let(:update_columns) { { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
208
223
  should_support_on_duplicate_key_update
209
224
  should_update_fields_mentioned_with_hash_mappings
210
225
  end
211
226
 
212
227
  context "using symbol hash map" do
213
- let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
228
+ let(:update_columns) { { title: :title, author_email_address: :author_email_address, parent_id: :parent_id } }
214
229
  should_support_on_duplicate_key_update
215
230
  should_update_fields_mentioned
216
231
  end
217
232
 
218
233
  context "using symbol hash map, but specifying column mismatches" do
219
- let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
234
+ let(:update_columns) { { title: :author_email_address, author_email_address: :title, parent_id: :parent_id } }
220
235
  should_support_on_duplicate_key_update
221
236
  should_update_fields_mentioned_with_hash_mappings
222
237
  end
223
238
  end
224
239
 
225
240
  context "with :constraint_name" do
226
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
227
- let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
228
- let(:updated_values){ [ [ 100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
241
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
242
+ let(:values) { [[100, "Book", "John Doe", "john@doe.com", 17]] }
243
+ let(:updated_values) { [[100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
229
244
 
230
245
  macro(:perform_import) do |*opts|
231
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :constraint_name => :topics_pkey, :columns => update_columns }, :validate => false)
246
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { constraint_name: :topics_pkey, columns: update_columns }, validate: false)
232
247
  end
233
248
 
234
249
  setup do
235
- Topic.import columns, values, :validate => false
250
+ Topic.import columns, values, validate: false
236
251
  @topic = Topic.find 100
237
252
  end
238
253
 
239
- let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
254
+ let(:update_columns) { [:title, :author_email_address, :parent_id] }
240
255
  should_support_on_duplicate_key_update
241
256
  should_update_fields_mentioned
242
257
  end
243
258
 
244
259
  context "with no :conflict_target or :constraint_name" do
245
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
246
- let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
247
- let(:updated_values){ [ [ 100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
260
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
261
+ let(:values) { [[100, "Book", "John Doe", "john@doe.com", 17]] }
262
+ let(:updated_values) { [[100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
248
263
 
249
264
  macro(:perform_import) do |*opts|
250
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :columns => update_columns }, :validate => false)
265
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { columns: update_columns }, validate: false)
251
266
  end
252
267
 
253
268
  setup do
254
- Topic.import columns, values, :validate => false
269
+ Topic.import columns, values, validate: false
255
270
  @topic = Topic.find 100
256
271
  end
257
272
 
258
273
  context "default to the primary key" do
259
- let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
274
+ let(:update_columns) { [:title, :author_email_address, :parent_id] }
260
275
  should_support_on_duplicate_key_update
261
276
  should_update_fields_mentioned
262
277
  end
263
278
  end
264
279
 
265
280
  context "with no :columns" do
266
- let(:columns){ %w( id title author_name author_email_address ) }
267
- let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com" ] ] }
268
- let(:updated_values){ [ [ 100, "Title Should Not Change", "Author Should Not Change", "john@nogo.com" ] ] }
281
+ let(:columns) { %w( id title author_name author_email_address ) }
282
+ let(:values) { [[100, "Book", "John Doe", "john@doe.com"]] }
283
+ let(:updated_values) { [[100, "Title Should Not Change", "Author Should Not Change", "john@nogo.com"]] }
269
284
 
270
285
  macro(:perform_import) do |*opts|
271
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :conflict_target => :id }, :validate => false)
286
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: { conflict_target: :id }, validate: false)
272
287
  end
273
288
 
274
289
  setup do
275
- Topic.import columns, values, :validate => false
290
+ Topic.import columns, values, validate: false
276
291
  @topic = Topic.find 100
277
292
  end
278
293
 
279
294
  should_update_updated_at_on_timestamp_columns
280
295
  end
281
296
  end
297
+
298
+ context "with recursive: true" do
299
+ let(:new_topics) { Build(1, :topic_with_book) }
300
+
301
+ it "imports objects with associations" do
302
+ assert_difference "Topic.count", +1 do
303
+ Topic.import new_topics, recursive: true, on_duplicate_key_update: [:updated_at], validate: false
304
+ new_topics.each do |topic|
305
+ assert_not_nil topic.id
306
+ end
307
+ end
308
+ end
309
+ end
282
310
  end
283
311
  end
284
312
  end
@@ -2,8 +2,8 @@ def should_support_basic_on_duplicate_key_update
2
2
  describe "#import" do
3
3
  extend ActiveSupport::TestCase::ImportAssertions
4
4
 
5
- macro(:perform_import){ raise "supply your own #perform_import in a context below" }
6
- macro(:updated_topic){ Topic.find(@topic.id) }
5
+ macro(:perform_import) { raise "supply your own #perform_import in a context below" }
6
+ macro(:updated_topic) { Topic.find(@topic.id) }
7
7
 
8
8
  context "with :on_duplicate_key_update and validation checks turned off" do
9
9
  asssertion_group(:should_support_on_duplicate_key_update) do
@@ -13,51 +13,51 @@ def should_support_basic_on_duplicate_key_update
13
13
  should_update_updated_at_on_timestamp_columns
14
14
  end
15
15
 
16
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
17
- let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
18
- let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
16
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
17
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
18
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
19
19
 
20
20
  macro(:perform_import) do |*opts|
21
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns , :validate => false)
21
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
22
22
  end
23
23
 
24
24
  setup do
25
- Topic.import columns, values, :validate => false
25
+ Topic.import columns, values, validate: false
26
26
  @topic = Topic.find 99
27
27
  end
28
28
 
29
29
  context "using an empty array" do
30
- let(:update_columns){ [] }
30
+ let(:update_columns) { [] }
31
31
  should_not_update_fields_not_mentioned
32
32
  should_update_updated_at_on_timestamp_columns
33
33
  end
34
34
 
35
35
  context "using string column names" do
36
- let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
36
+ let(:update_columns) { %w(title author_email_address parent_id) }
37
37
  should_support_on_duplicate_key_update
38
38
  should_update_fields_mentioned
39
39
  end
40
40
 
41
41
  context "using symbol column names" do
42
- let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
42
+ let(:update_columns) { [:title, :author_email_address, :parent_id] }
43
43
  should_support_on_duplicate_key_update
44
44
  should_update_fields_mentioned
45
45
  end
46
46
  end
47
47
 
48
48
  context "with a table that has a non-standard primary key" do
49
- let(:columns){ [ :promotion_id, :code ] }
50
- let(:values){ [ [ 1, 'DISCOUNT1' ] ] }
51
- let(:updated_values){ [ [ 1, 'DISCOUNT2'] ] }
52
- let(:update_columns){ [ :code ] }
49
+ let(:columns) { [:promotion_id, :code] }
50
+ let(:values) { [[1, 'DISCOUNT1']] }
51
+ let(:updated_values) { [[1, 'DISCOUNT2']] }
52
+ let(:update_columns) { [:code] }
53
53
 
54
54
  macro(:perform_import) do |*opts|
55
- Promotion.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
55
+ Promotion.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
56
56
  end
57
- macro(:updated_promotion){ Promotion.find(@promotion.promotion_id) }
57
+ macro(:updated_promotion) { Promotion.find(@promotion.promotion_id) }
58
58
 
59
59
  setup do
60
- Promotion.import columns, values, :validate => false
60
+ Promotion.import columns, values, validate: false
61
61
  @promotion = Promotion.find 1
62
62
  end
63
63
 
@@ -68,17 +68,17 @@ def should_support_basic_on_duplicate_key_update
68
68
  end
69
69
 
70
70
  context "with :on_duplicate_key_update turned off" do
71
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
72
- let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
73
- let(:updated_values){ [ [ 100, "Book - 2nd Edition", "This should raise an exception", "john@nogo.com", 57 ] ] }
71
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
72
+ let(:values) { [[100, "Book", "John Doe", "john@doe.com", 17]] }
73
+ let(:updated_values) { [[100, "Book - 2nd Edition", "This should raise an exception", "john@nogo.com", 57]] }
74
74
 
75
75
  macro(:perform_import) do |*opts|
76
- # `:on_duplicate_key_update => false` is the tested feature
77
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => false, :validate => false)
76
+ # `on_duplicate_key_update: false` is the tested feature
77
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: false, validate: false)
78
78
  end
79
79
 
80
80
  setup do
81
- Topic.import columns, values, :validate => false
81
+ Topic.import columns, values, validate: false
82
82
  @topic = Topic.find 100
83
83
  end
84
84