activerecord-import 2.1.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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -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_adapter.rb +1 -1
  14. data/lib/activerecord-import/adapters/sqlite3_proxy_adapter.rb +9 -0
  15. data/lib/activerecord-import/adapters/trilogy_proxy_adapter.rb +9 -0
  16. data/lib/activerecord-import/base.rb +2 -2
  17. data/lib/activerecord-import/import.rb +243 -211
  18. data/lib/activerecord-import/version.rb +1 -1
  19. metadata +13 -200
  20. data/.github/workflows/test.yaml +0 -161
  21. data/.gitignore +0 -37
  22. data/.rubocop.yml +0 -118
  23. data/.rubocop_todo.yml +0 -30
  24. data/Brewfile +0 -5
  25. data/Dockerfile +0 -23
  26. data/Gemfile +0 -63
  27. data/Rakefile +0 -73
  28. data/activerecord-import.gemspec +0 -28
  29. data/benchmarks/README +0 -32
  30. data/benchmarks/benchmark.rb +0 -72
  31. data/benchmarks/lib/base.rb +0 -143
  32. data/benchmarks/lib/cli_parser.rb +0 -111
  33. data/benchmarks/lib/float.rb +0 -17
  34. data/benchmarks/lib/mysql2_benchmark.rb +0 -21
  35. data/benchmarks/lib/output_to_csv.rb +0 -21
  36. data/benchmarks/lib/output_to_html.rb +0 -66
  37. data/benchmarks/models/test_innodb.rb +0 -5
  38. data/benchmarks/models/test_memory.rb +0 -5
  39. data/benchmarks/models/test_myisam.rb +0 -5
  40. data/benchmarks/schema/mysql2_schema.rb +0 -18
  41. data/docker-compose.yml +0 -34
  42. data/gemfiles/5.2.gemfile +0 -4
  43. data/gemfiles/6.0.gemfile +0 -4
  44. data/gemfiles/6.1.gemfile +0 -4
  45. data/gemfiles/7.0.gemfile +0 -4
  46. data/gemfiles/7.1.gemfile +0 -3
  47. data/gemfiles/7.2.gemfile +0 -3
  48. data/gemfiles/8.0.gemfile +0 -3
  49. data/test/adapters/jdbcmysql.rb +0 -3
  50. data/test/adapters/jdbcpostgresql.rb +0 -3
  51. data/test/adapters/jdbcsqlite3.rb +0 -3
  52. data/test/adapters/makara_postgis.rb +0 -3
  53. data/test/adapters/mysql2.rb +0 -3
  54. data/test/adapters/mysql2_makara.rb +0 -3
  55. data/test/adapters/mysql2_proxy.rb +0 -3
  56. data/test/adapters/mysql2spatial.rb +0 -3
  57. data/test/adapters/postgis.rb +0 -3
  58. data/test/adapters/postgresql.rb +0 -3
  59. data/test/adapters/postgresql_makara.rb +0 -3
  60. data/test/adapters/postgresql_proxy.rb +0 -3
  61. data/test/adapters/seamless_database_pool.rb +0 -3
  62. data/test/adapters/spatialite.rb +0 -3
  63. data/test/adapters/sqlite3.rb +0 -3
  64. data/test/adapters/trilogy.rb +0 -11
  65. data/test/database.yml.sample +0 -65
  66. data/test/github/database.yml +0 -78
  67. data/test/import_test.rb +0 -970
  68. data/test/jdbcmysql/import_test.rb +0 -7
  69. data/test/jdbcpostgresql/import_test.rb +0 -6
  70. data/test/jdbcsqlite3/import_test.rb +0 -6
  71. data/test/makara_postgis/import_test.rb +0 -10
  72. data/test/models/account.rb +0 -5
  73. data/test/models/alarm.rb +0 -4
  74. data/test/models/animal.rb +0 -8
  75. data/test/models/author.rb +0 -9
  76. data/test/models/bike_maker.rb +0 -10
  77. data/test/models/book.rb +0 -18
  78. data/test/models/car.rb +0 -5
  79. data/test/models/card.rb +0 -5
  80. data/test/models/chapter.rb +0 -6
  81. data/test/models/composite_book.rb +0 -19
  82. data/test/models/composite_chapter.rb +0 -12
  83. data/test/models/customer.rb +0 -18
  84. data/test/models/deck.rb +0 -8
  85. data/test/models/dictionary.rb +0 -6
  86. data/test/models/discount.rb +0 -5
  87. data/test/models/end_note.rb +0 -6
  88. data/test/models/group.rb +0 -5
  89. data/test/models/order.rb +0 -17
  90. data/test/models/playing_card.rb +0 -4
  91. data/test/models/promotion.rb +0 -5
  92. data/test/models/question.rb +0 -5
  93. data/test/models/rule.rb +0 -5
  94. data/test/models/tag.rb +0 -12
  95. data/test/models/tag_alias.rb +0 -11
  96. data/test/models/topic.rb +0 -31
  97. data/test/models/user.rb +0 -5
  98. data/test/models/user_token.rb +0 -6
  99. data/test/models/vendor.rb +0 -9
  100. data/test/models/widget.rb +0 -33
  101. data/test/mysql2/import_test.rb +0 -7
  102. data/test/mysql2_makara/import_test.rb +0 -8
  103. data/test/mysql2_proxy/import_test.rb +0 -6
  104. data/test/mysqlspatial2/import_test.rb +0 -8
  105. data/test/postgis/import_test.rb +0 -10
  106. data/test/postgresql/import_test.rb +0 -6
  107. data/test/postgresql_proxy/import_test.rb +0 -6
  108. data/test/schema/generic_schema.rb +0 -230
  109. data/test/schema/jdbcpostgresql_schema.rb +0 -3
  110. data/test/schema/mysql2_schema.rb +0 -21
  111. data/test/schema/postgis_schema.rb +0 -3
  112. data/test/schema/postgresql_schema.rb +0 -94
  113. data/test/schema/sqlite3_schema.rb +0 -15
  114. data/test/schema/version.rb +0 -12
  115. data/test/sqlite3/import_test.rb +0 -6
  116. data/test/support/active_support/test_case_extensions.rb +0 -73
  117. data/test/support/assertions.rb +0 -75
  118. data/test/support/factories.rb +0 -66
  119. data/test/support/generate.rb +0 -31
  120. data/test/support/mysql/import_examples.rb +0 -97
  121. data/test/support/postgresql/import_examples.rb +0 -642
  122. data/test/support/shared_examples/on_duplicate_key_ignore.rb +0 -45
  123. data/test/support/shared_examples/on_duplicate_key_update.rb +0 -437
  124. data/test/support/shared_examples/recursive_import.rb +0 -352
  125. data/test/support/sqlite3/import_examples.rb +0 -232
  126. data/test/synchronize_test.rb +0 -43
  127. data/test/test_helper.rb +0 -91
  128. data/test/trilogy/import_test.rb +0 -7
  129. data/test/value_sets_bytes_parser_test.rb +0 -106
  130. data/test/value_sets_records_parser_test.rb +0 -34
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.expand_path("#{File.dirname(__FILE__)}/postgresql_schema")
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveRecord::Schema.define do
4
- create_table :books, force: :cascade do |t|
5
- t.string :title, null: false
6
- t.virtual :upper_title, type: :string, as: "upper(`title`)" if t.respond_to?(:virtual)
7
- t.string :publisher, null: false, default: 'Default Publisher'
8
- t.string :author_name, null: false
9
- t.datetime :created_at
10
- t.datetime :created_on
11
- t.datetime :updated_at
12
- t.datetime :updated_on
13
- t.date :publish_date
14
- t.integer :topic_id
15
- t.integer :tag_id
16
- t.integer :publisher_id
17
- t.boolean :for_sale, default: true
18
- t.integer :status, default: 0
19
- t.string :type
20
- end
21
- end
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.expand_path("#{File.dirname(__FILE__)}/postgresql_schema")
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveRecord::Schema.define do
4
- execute('CREATE extension IF NOT EXISTS "hstore";')
5
- execute('CREATE extension IF NOT EXISTS "pgcrypto";')
6
- execute('CREATE extension IF NOT EXISTS "uuid-ossp";')
7
-
8
- # create ENUM if it does not exist yet
9
- begin
10
- execute('CREATE TYPE vendor_type AS ENUM (\'wholesaler\', \'retailer\');')
11
- rescue ActiveRecord::StatementInvalid
12
- execute('ALTER TYPE vendor_type ADD VALUE IF NOT EXISTS \'wholesaler\';')
13
- execute('ALTER TYPE vendor_type ADD VALUE IF NOT EXISTS \'retailer\';')
14
- end
15
-
16
- create_table :vendors, id: :uuid, force: :cascade do |t|
17
- t.string :name, null: true
18
- t.text :hours
19
- t.text :preferences
20
-
21
- if t.respond_to?(:json)
22
- t.json :pure_json_data
23
- t.json :data
24
- else
25
- t.text :data
26
- end
27
-
28
- if t.respond_to?(:hstore)
29
- t.hstore :config
30
- else
31
- t.text :config
32
- end
33
-
34
- if t.respond_to?(:jsonb)
35
- t.jsonb :pure_jsonb_data
36
- t.jsonb :settings
37
- t.jsonb :json_data, null: false, default: {}
38
- else
39
- t.text :settings
40
- t.text :json_data
41
- end
42
-
43
- t.column :vendor_type, :vendor_type
44
-
45
- t.datetime :created_at
46
- t.datetime :updated_at
47
- end
48
-
49
- create_table :alarms, force: true do |t|
50
- t.column :device_id, :integer, null: false
51
- t.column :alarm_type, :integer, null: false
52
- t.column :status, :integer, null: false
53
- t.column :metadata, :text
54
- t.column :secret_key, :binary
55
- t.datetime :created_at
56
- t.datetime :updated_at
57
- end
58
-
59
- add_index :alarms, [:device_id, :alarm_type], unique: true, where: 'status <> 0'
60
-
61
- unless ENV["SKIP_COMPOSITE_PK"]
62
- create_table :authors, force: :cascade do |t|
63
- t.string :name
64
- end
65
-
66
- execute %(
67
- DROP SEQUENCE IF EXISTS composite_book_id_seq CASCADE;
68
- CREATE SEQUENCE composite_book_id_seq
69
- AS integer
70
- START WITH 1
71
- INCREMENT BY 1
72
- NO MINVALUE
73
- NO MAXVALUE
74
- CACHE 1;
75
-
76
- DROP TABLE IF EXISTS composite_books;
77
- CREATE TABLE composite_books (
78
- id bigint DEFAULT nextval('composite_book_id_seq'::regclass) NOT NULL,
79
- title character varying,
80
- author_id bigint
81
- );
82
-
83
- ALTER TABLE ONLY composite_books ADD CONSTRAINT fk_rails_040a418131 FOREIGN KEY (author_id) REFERENCES authors(id);
84
- ).split.join(' ').strip
85
- end
86
-
87
- create_table :composite_chapters, force: :cascade do |t|
88
- t.string :title
89
- t.integer :composite_book_id, null: false
90
- t.integer :author_id, null: false
91
- t.datetime :created_at
92
- t.datetime :updated_at
93
- end
94
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveRecord::Schema.define do
4
- create_table :alarms, force: true do |t|
5
- t.column :device_id, :integer, null: false
6
- t.column :alarm_type, :integer, null: false
7
- t.column :status, :integer, null: false
8
- t.column :metadata, :text
9
- t.column :secret_key, :binary
10
- t.datetime :created_at
11
- t.datetime :updated_at
12
- end
13
-
14
- add_index :alarms, [:device_id, :alarm_type], unique: true, where: 'status <> 0'
15
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SchemaInfo < ActiveRecord::Base
4
- if respond_to?(:table_name=)
5
- self.table_name = 'schema_info'
6
- else
7
- # this is becoming deprecated in ActiveRecord but not all adapters supported it
8
- # at this time
9
- set_table_name 'schema_info'
10
- end
11
- VERSION = 12
12
- end
@@ -1,6 +0,0 @@
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/sqlite3/import_examples")
5
-
6
- should_support_sqlite3_import_functionality
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveSupport::TestCase
4
- include ActiveRecord::TestFixtures
5
-
6
- self.use_transactional_tests = true
7
-
8
- class << self
9
- def requires_active_record_version(version_string, &blk)
10
- return unless Gem::Dependency.new('', version_string).match?('', ActiveRecord::VERSION::STRING)
11
- instance_eval(&blk)
12
- end
13
-
14
- def assertion(name, &block)
15
- mc = class << self; self; end
16
- mc.class_eval do
17
- define_method(name) do
18
- it(name, &block)
19
- end
20
- end
21
- end
22
-
23
- def asssertion_group(name, &block)
24
- mc = class << self; self; end
25
- mc.class_eval do
26
- define_method(name, &block)
27
- end
28
- end
29
-
30
- def macro(name, &block)
31
- class_eval do
32
- define_method(name, &block)
33
- end
34
- end
35
-
36
- def describe(description, toplevel = nil, &blk)
37
- text = toplevel ? description : "#{name} #{description}"
38
- klass = Class.new(self)
39
-
40
- klass.class_eval <<-RUBY_EVAL
41
- def self.name
42
- "#{text}"
43
- end
44
- RUBY_EVAL
45
-
46
- # do not inherit test methods from the superclass
47
- klass.class_eval do
48
- instance_methods.grep(/^test.+/) do |method|
49
- undef_method method
50
- end
51
- end
52
-
53
- klass.instance_eval(&blk)
54
- end
55
- alias context describe
56
-
57
- def let(name, &blk)
58
- define_method(name) do
59
- instance_variable_name = "@__let_#{name}"
60
- return instance_variable_get(instance_variable_name) if instance_variable_defined?(instance_variable_name)
61
- instance_variable_set(instance_variable_name, instance_eval(&blk))
62
- end
63
- end
64
-
65
- def it(description, &blk)
66
- define_method("test_#{name}_#{description}", &blk)
67
- end
68
- end
69
- end
70
-
71
- def describe(description, &blk)
72
- ActiveSupport::TestCase.describe(description, true, &blk)
73
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveSupport::TestCase
4
- module ImportAssertions
5
- def self.extended(klass)
6
- klass.instance_eval do
7
- assertion(:should_not_update_created_at_on_timestamp_columns) do
8
- Timecop.freeze Chronic.parse("5 minutes from now") do
9
- perform_import
10
- assert_in_delta @topic.created_at.to_i, updated_topic.created_at.to_i, 1
11
- assert_in_delta @topic.created_on.to_i, updated_topic.created_on.to_i, 1
12
- end
13
- end
14
-
15
- assertion(:should_update_updated_at_on_timestamp_columns) do
16
- time = Chronic.parse("5 minutes from now")
17
- Timecop.freeze time do
18
- perform_import
19
- assert_in_delta time.to_i, updated_topic.updated_at.to_i, 1
20
- assert_in_delta time.to_i, updated_topic.updated_on.to_i, 1
21
- end
22
- end
23
-
24
- assertion(:should_not_update_updated_at_on_timestamp_columns) do
25
- time = Chronic.parse("5 minutes from now")
26
- Timecop.freeze time do
27
- perform_import
28
- assert_in_delta @topic.updated_at.to_i, updated_topic.updated_at.to_i, 1
29
- assert_in_delta @topic.updated_on.to_i, updated_topic.updated_on.to_i, 1
30
- end
31
- end
32
-
33
- assertion(:should_not_update_timestamps) do
34
- Timecop.freeze Chronic.parse("5 minutes from now") do
35
- perform_import timestamps: false
36
- assert_in_delta @topic.created_at.to_i, updated_topic.created_at.to_i, 1
37
- assert_in_delta @topic.created_on.to_i, updated_topic.created_on.to_i, 1
38
- assert_in_delta @topic.updated_at.to_i, updated_topic.updated_at.to_i, 1
39
- assert_in_delta @topic.updated_on.to_i, updated_topic.updated_on.to_i, 1
40
- end
41
- end
42
-
43
- assertion(:should_not_update_fields_not_mentioned) do
44
- assert_equal "John Doe", updated_topic.author_name
45
- end
46
-
47
- assertion(:should_update_fields_mentioned) do
48
- perform_import
49
- assert_equal "Book - 2nd Edition", updated_topic.title
50
- assert_equal "johndoe@example.com", updated_topic.author_email_address
51
- end
52
-
53
- assertion(:should_raise_update_fields_mentioned) do
54
- assert_raise ActiveRecord::RecordNotUnique do
55
- perform_import
56
- end
57
-
58
- assert_equal "Book", updated_topic.title
59
- assert_equal "john@doe.com", updated_topic.author_email_address
60
- end
61
-
62
- assertion(:should_update_fields_mentioned_with_hash_mappings) do
63
- perform_import
64
- assert_equal "johndoe@example.com", updated_topic.title
65
- assert_equal "Book - 2nd Edition", updated_topic.author_email_address
66
- end
67
-
68
- assertion(:should_update_foreign_keys) do
69
- perform_import
70
- assert_equal 57, updated_topic.parent_id
71
- end
72
- end
73
- end
74
- end
75
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- FactoryBot.define do
4
- sequence(:book_title) { |n| "Book #{n}" }
5
- sequence(:chapter_title) { |n| "Chapter #{n}" }
6
- sequence(:end_note) { |n| "Endnote #{n}" }
7
-
8
- factory :group do
9
- sequence(:order) { |n| "Order #{n}" }
10
- end
11
-
12
- factory :invalid_topic, class: "Topic" do
13
- sequence(:title) { |n| "Title #{n}" }
14
- author_name { nil }
15
- end
16
-
17
- factory :topic do
18
- sequence(:title) { |n| "Title #{n}" }
19
- sequence(:author_name) { |n| "Author #{n}" }
20
- sequence(:content) { |n| "Content #{n}" }
21
- end
22
-
23
- factory :widget do
24
- sequence(:w_id) { |n| n }
25
- end
26
-
27
- factory :question do
28
- sequence(:body) { |n| "Text #{n}" }
29
-
30
- trait :with_rule do
31
- after(:build) do |question|
32
- question.build_rule(FactoryBot.attributes_for(:rule))
33
- end
34
- end
35
- end
36
-
37
- factory :rule do
38
- sequence(:id) { |n| n }
39
- sequence(:condition_text) { |n| "q_#{n}_#{n}" }
40
- end
41
-
42
- factory :topic_with_book, parent: :topic do
43
- after(:build) do |topic|
44
- 2.times do
45
- book = topic.books.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
46
- 3.times do
47
- book.chapters.build(title: FactoryBot.generate(:chapter_title))
48
- end
49
-
50
- 4.times do
51
- book.end_notes.build(note: FactoryBot.generate(:end_note))
52
- end
53
- end
54
- end
55
- end
56
-
57
- factory :book do
58
- title { 'Tortilla Flat' }
59
- author_name { 'John Steinbeck' }
60
- end
61
-
62
- factory :car do
63
- sequence(:Name) { |n| n }
64
- sequence(:Features) { |n| "Feature #{n}" }
65
- end
66
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveSupport::TestCase
4
- def Build(*args) # rubocop:disable Naming/MethodName
5
- n = args.shift if args.first.is_a?(Numeric)
6
- factory = args.shift
7
- factory_bot_args = args.shift || {}
8
-
9
- if n
10
- [].tap do |collection|
11
- n.times.each { collection << FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args) }
12
- end
13
- else
14
- FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args)
15
- end
16
- end
17
-
18
- def Generate(*args) # rubocop:disable Naming/MethodName
19
- n = args.shift if args.first.is_a?(Numeric)
20
- factory = args.shift
21
- factory_bot_args = args.shift || {}
22
-
23
- if n
24
- [].tap do |collection|
25
- n.times.each { collection << FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args) }
26
- end
27
- else
28
- FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args)
29
- end
30
- end
31
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def should_support_mysql_import_functionality
4
- # Forcefully disable strict mode for this session.
5
- ActiveRecord::Base.connection.execute "set sql_mode='STRICT_ALL_TABLES'"
6
-
7
- should_support_basic_on_duplicate_key_update
8
- should_support_on_duplicate_key_ignore
9
-
10
- describe "#import" do
11
- context "with :on_duplicate_key_update and validation checks turned off" do
12
- extend ActiveSupport::TestCase::ImportAssertions
13
-
14
- asssertion_group(:should_support_on_duplicate_key_update) do
15
- should_not_update_fields_not_mentioned
16
- should_update_foreign_keys
17
- should_not_update_created_at_on_timestamp_columns
18
- should_update_updated_at_on_timestamp_columns
19
- end
20
-
21
- macro(:perform_import) { raise "supply your own #perform_import in a context below" }
22
- macro(:updated_topic) { Topic.find(@topic.id) }
23
-
24
- let(:columns) { %w( id title author_name author_email_address parent_id ) }
25
- let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
26
- let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
27
-
28
- macro(:perform_import) do |*opts|
29
- Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
30
- end
31
-
32
- setup do
33
- Topic.import columns, values, validate: false
34
- @topic = Topic.find 99
35
- end
36
-
37
- context "using string hash map" do
38
- let(:update_columns) { { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
39
- should_support_on_duplicate_key_update
40
- should_update_fields_mentioned
41
- end
42
-
43
- context "using string hash map, but specifying column mismatches" do
44
- let(:update_columns) { { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
45
- should_support_on_duplicate_key_update
46
- should_update_fields_mentioned_with_hash_mappings
47
- end
48
-
49
- context "using symbol hash map" do
50
- let(:update_columns) { { title: :title, author_email_address: :author_email_address, parent_id: :parent_id } }
51
- should_support_on_duplicate_key_update
52
- should_update_fields_mentioned
53
- end
54
-
55
- context "using symbol hash map, but specifying column mismatches" do
56
- let(:update_columns) { { title: :author_email_address, author_email_address: :title, parent_id: :parent_id } }
57
- should_support_on_duplicate_key_update
58
- should_update_fields_mentioned_with_hash_mappings
59
- end
60
- end
61
-
62
- context "with :synchronization option" do
63
- let(:topics) { [] }
64
- let(:values) { [[topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"]] }
65
- let(:columns) { %w(id author_name title) }
66
-
67
- setup do
68
- topics << Topic.create!(title: "LDAP", author_name: "Big Bird", content: "Putting Directories to Work.")
69
- topics << Topic.create!(title: "Rails Recipes", author_name: "Elmo", content: "A trusted collection of solutions.")
70
- end
71
-
72
- it "synchronizes passed in ActiveRecord model instances with the data just imported" do
73
- columns2update = ['author_name']
74
-
75
- expected_count = Topic.count
76
- Topic.import( columns, values,
77
- validate: false,
78
- on_duplicate_key_update: columns2update,
79
- synchronize: topics )
80
-
81
- assert_equal expected_count, Topic.count, "no new records should have been created!"
82
- assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
83
- assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
84
- end
85
- end
86
-
87
- context "with virtual columns" do
88
- let(:books) { [Book.new(author_name: "foo", title: "bar")] }
89
-
90
- it "ignores virtual columns and creates record" do
91
- assert_difference "Book.count", +1 do
92
- Book.import books
93
- end
94
- end
95
- end
96
- end
97
- end