activerecord-import 0.22.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yaml +107 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +74 -8
  5. data/Brewfile +3 -1
  6. data/CHANGELOG.md +235 -3
  7. data/Gemfile +22 -15
  8. data/LICENSE +21 -56
  9. data/README.markdown +574 -22
  10. data/Rakefile +4 -1
  11. data/activerecord-import.gemspec +6 -5
  12. data/benchmarks/benchmark.rb +7 -1
  13. data/benchmarks/lib/base.rb +2 -0
  14. data/benchmarks/lib/cli_parser.rb +3 -1
  15. data/benchmarks/lib/float.rb +2 -0
  16. data/benchmarks/lib/mysql2_benchmark.rb +2 -0
  17. data/benchmarks/lib/output_to_csv.rb +2 -0
  18. data/benchmarks/lib/output_to_html.rb +4 -2
  19. data/benchmarks/models/test_innodb.rb +2 -0
  20. data/benchmarks/models/test_memory.rb +2 -0
  21. data/benchmarks/models/test_myisam.rb +2 -0
  22. data/benchmarks/schema/{mysql_schema.rb → mysql2_schema.rb} +2 -0
  23. data/gemfiles/4.2.gemfile +2 -0
  24. data/gemfiles/5.0.gemfile +2 -0
  25. data/gemfiles/5.1.gemfile +2 -0
  26. data/gemfiles/5.2.gemfile +4 -0
  27. data/gemfiles/6.0.gemfile +4 -0
  28. data/gemfiles/6.1.gemfile +4 -0
  29. data/gemfiles/7.0.gemfile +4 -0
  30. data/lib/activerecord-import/active_record/adapters/abstract_adapter.rb +2 -0
  31. data/lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb +6 -4
  32. data/lib/activerecord-import/active_record/adapters/jdbcpostgresql_adapter.rb +2 -0
  33. data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +2 -0
  34. data/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb +2 -0
  35. data/lib/activerecord-import/active_record/adapters/postgresql_adapter.rb +2 -0
  36. data/lib/activerecord-import/active_record/adapters/seamless_database_pool_adapter.rb +2 -0
  37. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +2 -0
  38. data/lib/activerecord-import/adapters/abstract_adapter.rb +10 -2
  39. data/lib/activerecord-import/adapters/em_mysql2_adapter.rb +2 -0
  40. data/lib/activerecord-import/adapters/mysql2_adapter.rb +2 -0
  41. data/lib/activerecord-import/adapters/mysql_adapter.rb +19 -11
  42. data/lib/activerecord-import/adapters/postgresql_adapter.rb +56 -37
  43. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +128 -9
  44. data/lib/activerecord-import/base.rb +12 -2
  45. data/lib/activerecord-import/import.rb +300 -136
  46. data/lib/activerecord-import/mysql2.rb +2 -0
  47. data/lib/activerecord-import/postgresql.rb +2 -0
  48. data/lib/activerecord-import/sqlite3.rb +2 -0
  49. data/lib/activerecord-import/synchronize.rb +4 -2
  50. data/lib/activerecord-import/value_sets_parser.rb +4 -0
  51. data/lib/activerecord-import/version.rb +3 -1
  52. data/lib/activerecord-import.rb +4 -1
  53. data/test/adapters/jdbcmysql.rb +2 -0
  54. data/test/adapters/jdbcpostgresql.rb +2 -0
  55. data/test/adapters/jdbcsqlite3.rb +2 -0
  56. data/test/adapters/makara_postgis.rb +3 -0
  57. data/test/adapters/mysql2.rb +2 -0
  58. data/test/adapters/mysql2_makara.rb +2 -0
  59. data/test/adapters/mysql2spatial.rb +2 -0
  60. data/test/adapters/postgis.rb +2 -0
  61. data/test/adapters/postgresql.rb +2 -0
  62. data/test/adapters/postgresql_makara.rb +2 -0
  63. data/test/adapters/seamless_database_pool.rb +2 -0
  64. data/test/adapters/spatialite.rb +2 -0
  65. data/test/adapters/sqlite3.rb +2 -0
  66. data/test/{travis → github}/database.yml +3 -1
  67. data/test/import_test.rb +159 -8
  68. data/test/jdbcmysql/import_test.rb +2 -0
  69. data/test/jdbcpostgresql/import_test.rb +2 -0
  70. data/test/jdbcsqlite3/import_test.rb +2 -0
  71. data/test/makara_postgis/import_test.rb +10 -0
  72. data/test/models/account.rb +5 -0
  73. data/test/models/alarm.rb +2 -0
  74. data/test/models/animal.rb +8 -0
  75. data/test/models/bike_maker.rb +9 -0
  76. data/test/models/book.rb +2 -0
  77. data/test/models/car.rb +2 -0
  78. data/test/models/card.rb +5 -0
  79. data/test/models/chapter.rb +2 -0
  80. data/test/models/customer.rb +8 -0
  81. data/test/models/deck.rb +8 -0
  82. data/test/models/dictionary.rb +2 -0
  83. data/test/models/discount.rb +2 -0
  84. data/test/models/end_note.rb +2 -0
  85. data/test/models/group.rb +2 -0
  86. data/test/models/order.rb +8 -0
  87. data/test/models/playing_card.rb +4 -0
  88. data/test/models/promotion.rb +2 -0
  89. data/test/models/question.rb +2 -0
  90. data/test/models/rule.rb +2 -0
  91. data/test/models/tag.rb +3 -0
  92. data/test/models/tag_alias.rb +5 -0
  93. data/test/models/topic.rb +2 -0
  94. data/test/models/user.rb +5 -0
  95. data/test/models/user_token.rb +6 -0
  96. data/test/models/vendor.rb +2 -0
  97. data/test/models/widget.rb +2 -0
  98. data/test/mysql2/import_test.rb +2 -0
  99. data/test/mysql2_makara/import_test.rb +2 -0
  100. data/test/mysqlspatial2/import_test.rb +2 -0
  101. data/test/postgis/import_test.rb +2 -0
  102. data/test/postgresql/import_test.rb +2 -0
  103. data/test/schema/generic_schema.rb +53 -0
  104. data/test/schema/jdbcpostgresql_schema.rb +2 -0
  105. data/test/schema/mysql2_schema.rb +21 -0
  106. data/test/schema/postgis_schema.rb +2 -0
  107. data/test/schema/postgresql_schema.rb +18 -0
  108. data/test/schema/sqlite3_schema.rb +15 -0
  109. data/test/schema/version.rb +2 -0
  110. data/test/sqlite3/import_test.rb +2 -0
  111. data/test/support/active_support/test_case_extensions.rb +2 -0
  112. data/test/support/assertions.rb +2 -0
  113. data/test/support/factories.rb +10 -8
  114. data/test/support/generate.rb +10 -8
  115. data/test/support/mysql/import_examples.rb +14 -1
  116. data/test/support/postgresql/import_examples.rb +140 -3
  117. data/test/support/shared_examples/on_duplicate_key_ignore.rb +2 -0
  118. data/test/support/shared_examples/on_duplicate_key_update.rb +263 -0
  119. data/test/support/shared_examples/recursive_import.rb +76 -4
  120. data/test/support/sqlite3/import_examples.rb +191 -26
  121. data/test/synchronize_test.rb +2 -0
  122. data/test/test_helper.rb +36 -3
  123. data/test/value_sets_bytes_parser_test.rb +2 -0
  124. data/test/value_sets_records_parser_test.rb +2 -0
  125. metadata +46 -18
  126. data/.travis.yml +0 -61
  127. data/gemfiles/3.2.gemfile +0 -2
  128. data/gemfiles/4.0.gemfile +0 -2
  129. data/gemfiles/4.1.gemfile +0 -2
  130. data/test/schema/mysql_schema.rb +0 -16
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  warn <<-MSG
2
4
  [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
3
5
  is deprecated. Update to autorequire using 'require "activerecord-import"'. See
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  warn <<-MSG
2
4
  [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
3
5
  is deprecated. Update to autorequire using 'require "activerecord-import"'. See
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  warn <<-MSG
2
4
  [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
3
5
  is deprecated. Update to autorequire using 'require "activerecord-import"'. See
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord # :nodoc:
2
4
  class Base # :nodoc:
3
5
  # Synchronizes the passed in ActiveRecord instances with data
@@ -39,8 +41,8 @@ module ActiveRecord # :nodoc:
39
41
 
40
42
  next unless matched_instance
41
43
 
42
- instance.send :clear_aggregation_cache
43
- instance.send :clear_association_cache
44
+ instance.instance_variable_set :@association_cache, {}
45
+ instance.send :clear_aggregation_cache if instance.respond_to?(:clear_aggregation_cache, true)
44
46
  instance.instance_variable_set :@attributes, matched_instance.instance_variable_get(:@attributes)
45
47
 
46
48
  if instance.respond_to?(:clear_changes_information)
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array'
4
+
1
5
  module ActiveRecord::Import
2
6
  class ValueSetTooLargeError < StandardError
3
7
  attr_reader :size
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Import
3
- VERSION = "0.22.0".freeze
5
+ VERSION = "1.4.1"
4
6
  end
5
7
  end
@@ -1,4 +1,7 @@
1
- # rubocop:disable Style/FileName
1
+ # rubocop:disable Naming/FileName
2
+ # frozen_string_literal: true
3
+
4
+ require "active_support/lazy_load_hooks"
2
5
 
3
6
  ActiveSupport.on_load(:active_record) do
4
7
  require "activerecord-import/base"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "jdbcmysql"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "jdbcpostgresql"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "jdbcsqlite3"
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV["ARE_DB"] = "postgis"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "mysql2"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "mysql2_makara"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "mysql2spatial"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "postgis"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "postgresql"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "postgresql"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "seamless_database_pool"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "spatialite"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ENV["ARE_DB"] = "sqlite3"
@@ -1,7 +1,8 @@
1
1
  common: &common
2
2
  username: root
3
- password:
3
+ password: root
4
4
  encoding: utf8
5
+ collation: utf8_general_ci
5
6
  host: localhost
6
7
  database: activerecord_import_test
7
8
 
@@ -37,6 +38,7 @@ oracle:
37
38
  postgresql: &postgresql
38
39
  <<: *common
39
40
  username: postgres
41
+ password: postgres
40
42
  adapter: postgresql
41
43
  min_messages: warning
42
44
 
data/test/import_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper', __FILE__)
2
4
 
3
5
  describe "#import" do
@@ -17,6 +19,11 @@ describe "#import" do
17
19
  assert_equal error.message, "Last argument should be a two dimensional array '[[]]'. First element in array was a String"
18
20
  end
19
21
 
22
+ it "warns you that you're passing more data than you ought to" do
23
+ error = assert_raise(ArgumentError) { Topic.import %w(title author_name), [['Author #1', 'Book #1', 0]] }
24
+ assert_equal error.message, "Number of values (8) exceeds number of columns (7)"
25
+ end
26
+
20
27
  it "should not produce an error when importing empty arrays" do
21
28
  assert_nothing_raised do
22
29
  Topic.import []
@@ -154,6 +161,25 @@ describe "#import" do
154
161
  Tag.import columns, values, validate: false
155
162
  end
156
163
  end
164
+
165
+ it "should import models that are required to belong to models with composite primary keys" do
166
+ tag = Tag.create!(tag_id: 1, publisher_id: 1, tag: 'Mystery')
167
+ valid_tag_alias = TagAlias.new(tag_id: tag.tag_id, parent_id: tag.publisher_id, alias: 'Detective')
168
+ invalid_tag_aliases = [
169
+ TagAlias.new(tag_id: nil, parent_id: nil, alias: 'Detective'),
170
+ TagAlias.new(tag_id: tag.tag_id, parent_id: nil, alias: 'Detective'),
171
+ TagAlias.new(tag_id: nil, parent_id: tag.publisher_id, alias: 'Detective'),
172
+ ]
173
+
174
+ assert_difference "TagAlias.count", +1 do
175
+ TagAlias.import [valid_tag_alias]
176
+ end
177
+ invalid_tag_aliases.each do |invalid_tag_alias|
178
+ assert_no_difference "TagAlias.count" do
179
+ TagAlias.import [invalid_tag_alias]
180
+ end
181
+ end
182
+ end
157
183
  end
158
184
  end
159
185
 
@@ -164,7 +190,17 @@ describe "#import" do
164
190
  assert_difference "Dictionary.count", +1 do
165
191
  Dictionary.import dictionaries
166
192
  end
167
- assert_equal "Dictionary", Dictionary.first.type
193
+ assert_equal "Dictionary", Dictionary.last.type
194
+ end
195
+
196
+ it "should import arrays successfully" do
197
+ columns = [:author_name, :title]
198
+ values = [["Noah Webster", "Webster's Dictionary"]]
199
+
200
+ assert_difference "Dictionary.count", +1 do
201
+ Dictionary.import columns, values
202
+ end
203
+ assert_equal "Dictionary", Dictionary.last.type
168
204
  end
169
205
  end
170
206
 
@@ -210,9 +246,9 @@ describe "#import" do
210
246
  end
211
247
 
212
248
  it "should ignore uniqueness validators" do
213
- Topic.import columns, valid_values, validate: true
249
+ Topic.import columns, valid_values
214
250
  assert_difference "Topic.count", +2 do
215
- Topic.import columns, valid_values, validate: true
251
+ Topic.import columns, valid_values
216
252
  end
217
253
  end
218
254
 
@@ -247,6 +283,16 @@ describe "#import" do
247
283
  end
248
284
  end
249
285
 
286
+ it "should index the failed instances by their poistion in the set if `track_failures` is true" do
287
+ index_offset = valid_values.length
288
+ results = Topic.import columns, valid_values + invalid_values, validate: true, track_validation_failures: true
289
+ assert_equal invalid_values.size, results.failed_instances.size
290
+ invalid_values.each_with_index do |value_set, index|
291
+ assert_equal index + index_offset, results.failed_instances[index].first
292
+ assert_equal value_set.first, results.failed_instances[index].last.title
293
+ end
294
+ end
295
+
250
296
  it "should set ids in valid models if adapter supports setting primary key of imported objects" do
251
297
  if ActiveRecord::Base.supports_setting_primary_key_of_imported_objects?
252
298
  Topic.import (invalid_models + valid_models), validate: true
@@ -294,6 +340,36 @@ describe "#import" do
294
340
  end
295
341
  end
296
342
  end
343
+
344
+ context "with uniqueness validators included" do
345
+ it "should not import duplicate records" do
346
+ Topic.import columns, valid_values
347
+ assert_no_difference "Topic.count" do
348
+ Topic.import columns, valid_values, validate_uniqueness: true
349
+ end
350
+ end
351
+ end
352
+
353
+ context "when validatoring presence of belongs_to association" do
354
+ it "should not import records without foreign key" do
355
+ assert_no_difference "UserToken.count" do
356
+ UserToken.import [:token], [['12345abcdef67890']]
357
+ end
358
+ end
359
+
360
+ it "should import records with foreign key" do
361
+ assert_difference "UserToken.count", +1 do
362
+ UserToken.import [:user_name, :token], [%w("Bob", "12345abcdef67890")]
363
+ end
364
+ end
365
+
366
+ it "should not mutate the defined validations" do
367
+ UserToken.import [:user_name, :token], [%w("Bob", "12345abcdef67890")]
368
+ ut = UserToken.new
369
+ ut.valid?
370
+ assert_includes ut.errors.messages, :user
371
+ end
372
+ end
297
373
  end
298
374
 
299
375
  context "without :validation option" do
@@ -360,6 +436,15 @@ describe "#import" do
360
436
  assert_equal 3, result.num_inserts if Topic.supports_import?
361
437
  end
362
438
  end
439
+
440
+ it "should accept and call an optional callable to run after each batch" do
441
+ lambda_called = 0
442
+
443
+ my_proc = ->(_row_count, _batches, _batch, _duration) { lambda_called += 1 }
444
+ Topic.import Build(10, :topics), batch_size: 4, batch_progress: my_proc
445
+
446
+ assert_equal 3, lambda_called
447
+ end
363
448
  end
364
449
 
365
450
  context "with :synchronize option" do
@@ -490,11 +575,15 @@ describe "#import" do
490
575
 
491
576
  context "when the timestamps columns are present" do
492
577
  setup do
493
- @existing_book = Book.create(title: "Fell", author_name: "Curry", publisher: "Bayer", created_at: 2.years.ago.utc, created_on: 2.years.ago.utc)
494
- ActiveRecord::Base.default_timezone = :utc
578
+ @existing_book = Book.create(title: "Fell", author_name: "Curry", publisher: "Bayer", created_at: 2.years.ago.utc, created_on: 2.years.ago.utc, updated_at: 2.years.ago.utc, updated_on: 2.years.ago.utc)
579
+ if ActiveRecord.respond_to?(:default_timezone)
580
+ ActiveRecord.default_timezone = :utc
581
+ else
582
+ ActiveRecord::Base.default_timezone = :utc
583
+ end
495
584
  Timecop.freeze(time) do
496
585
  assert_difference "Book.count", +2 do
497
- Book.import %w(title author_name publisher created_at created_on), [["LDAP", "Big Bird", "Del Rey", nil, nil], [@existing_book.title, @existing_book.author_name, @existing_book.publisher, @existing_book.created_at, @existing_book.created_on]]
586
+ Book.import %w(title author_name publisher created_at created_on updated_at updated_on), [["LDAP", "Big Bird", "Del Rey", nil, nil, nil, nil], [@existing_book.title, @existing_book.author_name, @existing_book.publisher, @existing_book.created_at, @existing_book.created_on, @existing_book.updated_at, @existing_book.updated_on]]
498
587
  end
499
588
  end
500
589
  @new_book, @existing_book = Book.last 2
@@ -523,6 +612,23 @@ describe "#import" do
523
612
  it "should set the updated_on column for new records" do
524
613
  assert_in_delta time.to_i, @new_book.updated_on.to_i, 1.second
525
614
  end
615
+
616
+ it "should not set the updated_at column for existing records" do
617
+ assert_equal 2.years.ago.utc.strftime("%Y:%d"), @existing_book.updated_at.strftime("%Y:%d")
618
+ end
619
+
620
+ it "should not set the updated_on column for existing records" do
621
+ assert_equal 2.years.ago.utc.strftime("%Y:%d"), @existing_book.updated_on.strftime("%Y:%d")
622
+ end
623
+
624
+ it "should not set the updated_at column on models if changed" do
625
+ timestamp = Time.now.utc
626
+ books = [
627
+ Book.new(author_name: "Foo", title: "Baz", created_at: timestamp, updated_at: timestamp)
628
+ ]
629
+ Book.import books
630
+ assert_equal timestamp.strftime("%Y:%d"), Book.last.updated_at.strftime("%Y:%d")
631
+ end
526
632
  end
527
633
 
528
634
  context "when a custom time zone is set" do
@@ -567,7 +673,7 @@ describe "#import" do
567
673
 
568
674
  context "importing through an association scope" do
569
675
  { has_many: :chapters, polymorphic: :discounts }.each do |association_type, association|
570
- book = FactoryGirl.create :book
676
+ book = FactoryBot.create :book
571
677
  scope = book.public_send association
572
678
  klass = { chapters: Chapter, discounts: Discount }[association]
573
679
  column = { chapters: :title, discounts: :amount }[association]
@@ -590,18 +696,34 @@ describe "#import" do
590
696
  assert_equal [val1, val2], scope.map(&column).sort
591
697
  end
592
698
 
699
+ context "for cards and decks" do
700
+ it "works when the polymorphic name is different than base class name" do
701
+ deck = Deck.create(id: 1, name: 'test')
702
+ deck.cards.import [:id, :deck_type], [[1, 'PlayingCard']]
703
+ assert_equal deck.cards.first.deck_type, "PlayingCard"
704
+ end
705
+ end
706
+
593
707
  it "works importing array of hashes" do
594
708
  scope.import [{ column => val1 }, { column => val2 }]
595
709
 
596
710
  assert_equal [val1, val2], scope.map(&column).sort
597
711
  end
598
712
  end
713
+
714
+ it "works with a non-standard association primary key" do
715
+ user = User.create(id: 1, name: 'Solomon')
716
+ user.user_tokens.import [:id, :token], [[5, '12345abcdef67890']]
717
+
718
+ token = UserToken.find(5)
719
+ assert_equal 'Solomon', token.user_name
720
+ end
599
721
  end
600
722
  end
601
723
 
602
724
  context "importing model with polymorphic belongs_to" do
603
725
  it "works without error" do
604
- book = FactoryGirl.create :book
726
+ book = FactoryBot.create :book
605
727
  discount = Discount.new(discountable: book)
606
728
 
607
729
  Discount.import([discount])
@@ -840,4 +962,33 @@ describe "#import" do
840
962
  end
841
963
  end
842
964
  end
965
+ describe "importing model with after_initialize callback" do
966
+ let(:columns) { %w(name size) }
967
+ let(:valid_values) { [%w("Deer", "Small"), %w("Monkey", "Medium")] }
968
+ let(:invalid_values) do
969
+ [
970
+ { name: "giraffe", size: "Large" },
971
+ { size: "Medium" } # name is missing
972
+ ]
973
+ end
974
+ context "with validation checks turned off" do
975
+ it "should import valid data" do
976
+ Animal.import(columns, valid_values, validate: false)
977
+ assert_equal 2, Animal.count
978
+ end
979
+ it "should raise ArgumentError" do
980
+ assert_raise(ArgumentError) { Animal.import(invalid_values, validate: false) }
981
+ end
982
+ end
983
+
984
+ context "with validation checks turned on" do
985
+ it "should import valid data" do
986
+ Animal.import(columns, valid_values, validate: true)
987
+ assert_equal 2, Animal.count
988
+ end
989
+ it "should raise ArgumentError" do
990
+ assert_raise(ArgumentError) { Animal.import(invalid_values, validate: true) }
991
+ end
992
+ end
993
+ end
843
994
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
4
  require File.expand_path(File.dirname(__FILE__) + '/../support/assertions')
3
5
  require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
4
  require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples')
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
4
  require File.expand_path(File.dirname(__FILE__) + '/../support/sqlite3/import_examples')
3
5
 
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
4
+ require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples')
5
+
6
+ should_support_postgresql_import_functionality
7
+
8
+ if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
9
+ should_support_postgresql_upsert_functionality
10
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Account < ActiveRecord::Base
4
+ self.locking_column = :lock
5
+ end
data/test/models/alarm.rb CHANGED
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Alarm < ActiveRecord::Base
2
4
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Animal < ActiveRecord::Base
4
+ after_initialize :validate_name_presence, if: :new_record?
5
+ def validate_name_presence
6
+ raise ArgumentError if name.nil?
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bike
4
+ def self.table_name_prefix
5
+ 'bike_'
6
+ end
7
+ class Maker < ActiveRecord::Base
8
+ end
9
+ end
data/test/models/book.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Book < ActiveRecord::Base
2
4
  belongs_to :topic, inverse_of: :books
3
5
  belongs_to :tag, foreign_key: [:tag_id, :parent_id]
data/test/models/car.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Car < ActiveRecord::Base
2
4
  self.primary_key = :Name
3
5
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Card < ActiveRecord::Base
4
+ belongs_to :deck, polymorphic: true
5
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Chapter < ActiveRecord::Base
2
4
  belongs_to :book, inverse_of: :chapters
3
5
  validates :title, presence: true
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Customer < ActiveRecord::Base
4
+ has_many :orders,
5
+ inverse_of: :customer,
6
+ primary_key: %i(account_id id),
7
+ foreign_key: %i(account_id customer_id)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Deck < ActiveRecord::Base
4
+ has_many :cards
5
+ def self.polymorphic_name
6
+ "PlayingCard"
7
+ end
8
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'book'
2
4
 
3
5
  class Dictionary < Book
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Discount < ActiveRecord::Base
2
4
  belongs_to :discountable, polymorphic: true
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class EndNote < ActiveRecord::Base
2
4
  belongs_to :book, inverse_of: :end_notes
3
5
  validates :note, presence: true
data/test/models/group.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Group < ActiveRecord::Base
2
4
  self.table_name = 'group'
3
5
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Order < ActiveRecord::Base
4
+ belongs_to :customer,
5
+ inverse_of: :orders,
6
+ primary_key: %i(account_id id),
7
+ foreign_key: %i(account_id customer_id)
8
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PlayingCard < ActiveRecord::Base
4
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Promotion < ActiveRecord::Base
2
4
  self.primary_key = :promotion_id
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Question < ActiveRecord::Base
2
4
  has_one :rule
3
5
  end
data/test/models/rule.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Rule < ActiveRecord::Base
2
4
  belongs_to :question
3
5
  end
data/test/models/tag.rb CHANGED
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Tag < ActiveRecord::Base
2
4
  self.primary_keys = :tag_id, :publisher_id unless ENV["SKIP_COMPOSITE_PK"]
3
5
  has_many :books, inverse_of: :tag
6
+ has_many :tag_aliases, inverse_of: :tag
4
7
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TagAlias < ActiveRecord::Base
4
+ belongs_to :tag, foreign_key: [:tag_id, :parent_id], required: true
5
+ end
data/test/models/topic.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Topic < ActiveRecord::Base
2
4
  validates_presence_of :author_name
3
5
  validates :title, numericality: { only_integer: true }, on: :context_test
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User < ActiveRecord::Base
4
+ has_many :user_tokens, primary_key: :name, foreign_key: :user_name
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserToken < ActiveRecord::Base
4
+ belongs_to :user, primary_key: :name, foreign_key: :user_name
5
+ validates :user, presence: true
6
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Vendor < ActiveRecord::Base
2
4
  store :preferences, accessors: [:color], coder: JSON
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CustomCoder
2
4
  def load(value)
3
5
  if value.nil?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
4
  require File.expand_path(File.dirname(__FILE__) + '/../support/assertions')
3
5
  require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')