activerecord-import 0.10.0 → 1.0.8

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 (118) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +49 -0
  4. data/.rubocop_todo.yml +36 -0
  5. data/.travis.yml +64 -8
  6. data/CHANGELOG.md +475 -0
  7. data/Gemfile +32 -15
  8. data/LICENSE +21 -56
  9. data/README.markdown +564 -35
  10. data/Rakefile +20 -3
  11. data/activerecord-import.gemspec +7 -7
  12. data/benchmarks/README +2 -2
  13. data/benchmarks/benchmark.rb +68 -64
  14. data/benchmarks/lib/base.rb +138 -137
  15. data/benchmarks/lib/cli_parser.rb +107 -103
  16. data/benchmarks/lib/{mysql_benchmark.rb → mysql2_benchmark.rb} +19 -22
  17. data/benchmarks/lib/output_to_csv.rb +5 -4
  18. data/benchmarks/lib/output_to_html.rb +8 -13
  19. data/benchmarks/models/test_innodb.rb +1 -1
  20. data/benchmarks/models/test_memory.rb +1 -1
  21. data/benchmarks/models/test_myisam.rb +1 -1
  22. data/benchmarks/schema/mysql2_schema.rb +16 -0
  23. data/gemfiles/3.2.gemfile +2 -4
  24. data/gemfiles/4.0.gemfile +2 -4
  25. data/gemfiles/4.1.gemfile +2 -4
  26. data/gemfiles/4.2.gemfile +2 -4
  27. data/gemfiles/5.0.gemfile +2 -0
  28. data/gemfiles/5.1.gemfile +2 -0
  29. data/gemfiles/5.2.gemfile +2 -0
  30. data/gemfiles/6.0.gemfile +2 -0
  31. data/gemfiles/6.1.gemfile +1 -0
  32. data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +6 -0
  33. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
  34. data/lib/activerecord-import/adapters/abstract_adapter.rb +23 -17
  35. data/lib/activerecord-import/adapters/mysql_adapter.rb +52 -25
  36. data/lib/activerecord-import/adapters/postgresql_adapter.rb +187 -10
  37. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +148 -17
  38. data/lib/activerecord-import/base.rb +15 -9
  39. data/lib/activerecord-import/import.rb +740 -191
  40. data/lib/activerecord-import/synchronize.rb +21 -21
  41. data/lib/activerecord-import/value_sets_parser.rb +33 -8
  42. data/lib/activerecord-import/version.rb +1 -1
  43. data/lib/activerecord-import.rb +4 -15
  44. data/test/adapters/jdbcsqlite3.rb +1 -0
  45. data/test/adapters/makara_postgis.rb +1 -0
  46. data/test/adapters/mysql2_makara.rb +1 -0
  47. data/test/adapters/mysql2spatial.rb +1 -1
  48. data/test/adapters/postgis.rb +1 -1
  49. data/test/adapters/postgresql.rb +1 -1
  50. data/test/adapters/postgresql_makara.rb +1 -0
  51. data/test/adapters/spatialite.rb +1 -1
  52. data/test/adapters/sqlite3.rb +1 -1
  53. data/test/database.yml.sample +13 -18
  54. data/test/import_test.rb +608 -89
  55. data/test/jdbcmysql/import_test.rb +2 -3
  56. data/test/jdbcpostgresql/import_test.rb +0 -2
  57. data/test/jdbcsqlite3/import_test.rb +4 -0
  58. data/test/makara_postgis/import_test.rb +8 -0
  59. data/test/models/account.rb +3 -0
  60. data/test/models/alarm.rb +2 -0
  61. data/test/models/animal.rb +6 -0
  62. data/test/models/bike_maker.rb +7 -0
  63. data/test/models/book.rb +7 -6
  64. data/test/models/car.rb +3 -0
  65. data/test/models/chapter.rb +2 -2
  66. data/test/models/dictionary.rb +4 -0
  67. data/test/models/discount.rb +3 -0
  68. data/test/models/end_note.rb +2 -2
  69. data/test/models/promotion.rb +3 -0
  70. data/test/models/question.rb +3 -0
  71. data/test/models/rule.rb +3 -0
  72. data/test/models/tag.rb +4 -0
  73. data/test/models/topic.rb +17 -3
  74. data/test/models/user.rb +3 -0
  75. data/test/models/user_token.rb +4 -0
  76. data/test/models/vendor.rb +7 -0
  77. data/test/models/widget.rb +19 -2
  78. data/test/mysql2/import_test.rb +2 -3
  79. data/test/{em_mysql2 → mysql2_makara}/import_test.rb +1 -1
  80. data/test/mysqlspatial2/import_test.rb +2 -2
  81. data/test/postgis/import_test.rb +5 -1
  82. data/test/schema/generic_schema.rb +159 -85
  83. data/test/schema/jdbcpostgresql_schema.rb +1 -0
  84. data/test/schema/mysql2_schema.rb +19 -0
  85. data/test/schema/postgis_schema.rb +1 -0
  86. data/test/schema/postgresql_schema.rb +61 -0
  87. data/test/schema/sqlite3_schema.rb +13 -0
  88. data/test/sqlite3/import_test.rb +2 -50
  89. data/test/support/active_support/test_case_extensions.rb +21 -13
  90. data/test/support/{mysql/assertions.rb → assertions.rb} +20 -2
  91. data/test/support/factories.rb +39 -14
  92. data/test/support/generate.rb +10 -10
  93. data/test/support/mysql/import_examples.rb +49 -98
  94. data/test/support/postgresql/import_examples.rb +535 -57
  95. data/test/support/shared_examples/on_duplicate_key_ignore.rb +43 -0
  96. data/test/support/shared_examples/on_duplicate_key_update.rb +378 -0
  97. data/test/support/shared_examples/recursive_import.rb +225 -0
  98. data/test/support/sqlite3/import_examples.rb +231 -0
  99. data/test/synchronize_test.rb +10 -2
  100. data/test/test_helper.rb +36 -8
  101. data/test/travis/database.yml +26 -17
  102. data/test/value_sets_bytes_parser_test.rb +25 -17
  103. data/test/value_sets_records_parser_test.rb +6 -6
  104. metadata +86 -42
  105. data/benchmarks/boot.rb +0 -18
  106. data/benchmarks/schema/mysql_schema.rb +0 -16
  107. data/gemfiles/3.1.gemfile +0 -4
  108. data/lib/activerecord-import/active_record/adapters/em_mysql2_adapter.rb +0 -8
  109. data/lib/activerecord-import/active_record/adapters/mysql_adapter.rb +0 -6
  110. data/lib/activerecord-import/em_mysql2.rb +0 -7
  111. data/lib/activerecord-import/mysql.rb +0 -7
  112. data/test/adapters/em_mysql2.rb +0 -1
  113. data/test/adapters/mysql.rb +0 -1
  114. data/test/adapters/mysqlspatial.rb +0 -1
  115. data/test/mysql/import_test.rb +0 -6
  116. data/test/mysqlspatial/import_test.rb +0 -6
  117. data/test/schema/mysql_schema.rb +0 -18
  118. data/test/travis/build.sh +0 -30
@@ -1,52 +1,4 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../support/sqlite3/import_examples')
2
3
 
3
- describe "#supports_imports?" do
4
- context "and SQLite is 3.7.11 or higher" do
5
- it "supports import" do
6
- version = ActiveRecord::ConnectionAdapters::SQLite3Adapter::Version.new("3.7.11")
7
- assert ActiveRecord::Base.supports_import?(version)
8
-
9
- version = ActiveRecord::ConnectionAdapters::SQLite3Adapter::Version.new("3.7.12")
10
- assert ActiveRecord::Base.supports_import?(version)
11
- end
12
- end
13
-
14
- context "and SQLite less than 3.7.11" do
15
- it "doesn't support import" do
16
- version = ActiveRecord::ConnectionAdapters::SQLite3Adapter::Version.new("3.7.10")
17
- assert !ActiveRecord::Base.supports_import?(version)
18
- end
19
- end
20
- end
21
-
22
- describe "#import" do
23
- it "imports with a single insert on SQLite 3.7.11 or higher" do
24
- assert_difference "Topic.count", +507 do
25
- result = Topic.import Build(7, :topics)
26
- assert_equal 1, result.num_inserts, "Failed to issue a single INSERT statement. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
27
- assert_equal 7, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
28
-
29
- result = Topic.import Build(500, :topics)
30
- assert_equal 1, result.num_inserts, "Failed to issue a single INSERT statement. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
31
- assert_equal 507, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
32
- end
33
- end
34
-
35
- it "imports with a two inserts on SQLite 3.7.11 or higher" do
36
- assert_difference "Topic.count", +501 do
37
- result = Topic.import Build(501, :topics)
38
- assert_equal 2, result.num_inserts, "Failed to issue a two INSERT statements. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
39
- assert_equal 501, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
40
- end
41
- end
42
-
43
- it "imports with a five inserts on SQLite 3.7.11 or higher" do
44
- assert_difference "Topic.count", +2500 do
45
- result = Topic.import Build(2500, :topics)
46
- assert_equal 5, result.num_inserts, "Failed to issue a two INSERT statements. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
47
- assert_equal 2500, Topic.count, "Failed to insert all records. Make sure you have a supported version of SQLite3 (3.7.11 or higher) installed"
48
- end
49
- end
50
-
51
- end
52
-
4
+ should_support_sqlite3_import_functionality
@@ -1,19 +1,29 @@
1
1
  class ActiveSupport::TestCase
2
2
  include ActiveRecord::TestFixtures
3
- self.use_transactional_fixtures = true
4
-
3
+
4
+ if ENV['AR_VERSION'].to_f >= 5.0
5
+ self.use_transactional_tests = true
6
+ else
7
+ self.use_transactional_fixtures = true
8
+ end
9
+
5
10
  class << self
11
+ def requires_active_record_version(version_string, &blk)
12
+ return unless Gem::Dependency.new('', version_string).match?('', ActiveRecord::VERSION::STRING)
13
+ instance_eval(&blk)
14
+ end
15
+
6
16
  def assertion(name, &block)
7
- mc = class << self ; self ; end
17
+ mc = class << self; self; end
8
18
  mc.class_eval do
9
19
  define_method(name) do
10
20
  it(name, &block)
11
21
  end
12
22
  end
13
23
  end
14
-
24
+
15
25
  def asssertion_group(name, &block)
16
- mc = class << self ; self ; end
26
+ mc = class << self; self; end
17
27
  mc.class_eval do
18
28
  define_method(name, &block)
19
29
  end
@@ -24,8 +34,8 @@ class ActiveSupport::TestCase
24
34
  define_method(name, &block)
25
35
  end
26
36
  end
27
-
28
- def describe(description, toplevel=nil, &blk)
37
+
38
+ def describe(description, toplevel = nil, &blk)
29
39
  text = toplevel ? description : "#{name} #{description}"
30
40
  klass = Class.new(self)
31
41
 
@@ -42,10 +52,10 @@ class ActiveSupport::TestCase
42
52
  end
43
53
  end
44
54
 
45
- klass.instance_eval &blk
55
+ klass.instance_eval(&blk)
46
56
  end
47
- alias_method :context, :describe
48
-
57
+ alias context describe
58
+
49
59
  def let(name, &blk)
50
60
  define_method(name) do
51
61
  instance_variable_name = "@__let_#{name}"
@@ -53,15 +63,13 @@ class ActiveSupport::TestCase
53
63
  instance_variable_set(instance_variable_name, instance_eval(&blk))
54
64
  end
55
65
  end
56
-
66
+
57
67
  def it(description, &blk)
58
68
  define_method("test_#{name}_#{description}", &blk)
59
69
  end
60
70
  end
61
-
62
71
  end
63
72
 
64
73
  def describe(description, &blk)
65
74
  ActiveSupport::TestCase.describe(description, true, &blk)
66
75
  end
67
-
@@ -1,5 +1,5 @@
1
1
  class ActiveSupport::TestCase
2
- module MySQLAssertions
2
+ module ImportAssertions
3
3
  def self.extended(klass)
4
4
  klass.instance_eval do
5
5
  assertion(:should_not_update_created_at_on_timestamp_columns) do
@@ -19,9 +19,18 @@ class ActiveSupport::TestCase
19
19
  end
20
20
  end
21
21
 
22
+ assertion(:should_not_update_updated_at_on_timestamp_columns) do
23
+ time = Chronic.parse("5 minutes from now")
24
+ Timecop.freeze time do
25
+ perform_import
26
+ assert_in_delta @topic.updated_at.to_i, updated_topic.updated_at.to_i, 1
27
+ assert_in_delta @topic.updated_on.to_i, updated_topic.updated_on.to_i, 1
28
+ end
29
+ end
30
+
22
31
  assertion(:should_not_update_timestamps) do
23
32
  Timecop.freeze Chronic.parse("5 minutes from now") do
24
- perform_import :timestamps => false
33
+ perform_import timestamps: false
25
34
  assert_in_delta @topic.created_at.to_i, updated_topic.created_at.to_i, 1
26
35
  assert_in_delta @topic.created_on.to_i, updated_topic.created_on.to_i, 1
27
36
  assert_in_delta @topic.updated_at.to_i, updated_topic.updated_at.to_i, 1
@@ -39,6 +48,15 @@ class ActiveSupport::TestCase
39
48
  assert_equal "johndoe@example.com", updated_topic.author_email_address
40
49
  end
41
50
 
51
+ assertion(:should_raise_update_fields_mentioned) do
52
+ assert_raise ActiveRecord::RecordNotUnique do
53
+ perform_import
54
+ end
55
+
56
+ assert_equal "Book", updated_topic.title
57
+ assert_equal "john@doe.com", updated_topic.author_email_address
58
+ end
59
+
42
60
  assertion(:should_update_fields_mentioned_with_hash_mappings) do
43
61
  perform_import
44
62
  assert_equal "johndoe@example.com", updated_topic.title
@@ -1,39 +1,64 @@
1
- FactoryGirl.define do
2
- sequence(:book_title) {|n| "Book #{n}"}
3
- sequence(:chapter_title) {|n| "Chapter #{n}"}
4
- sequence(:end_note) {|n| "Endnote #{n}"}
1
+ FactoryBot.define do
2
+ sequence(:book_title) { |n| "Book #{n}" }
3
+ sequence(:chapter_title) { |n| "Chapter #{n}" }
4
+ sequence(:end_note) { |n| "Endnote #{n}" }
5
5
 
6
6
  factory :group do
7
7
  sequence(:order) { |n| "Order #{n}" }
8
8
  end
9
9
 
10
- factory :invalid_topic, :class => "Topic" do
11
- sequence(:title){ |n| "Title #{n}"}
12
- author_name nil
10
+ factory :invalid_topic, class: "Topic" do
11
+ sequence(:title) { |n| "Title #{n}" }
12
+ author_name { nil }
13
13
  end
14
14
 
15
15
  factory :topic do
16
- sequence(:title){ |n| "Title #{n}"}
17
- sequence(:author_name){ |n| "Author #{n}"}
16
+ sequence(:title) { |n| "Title #{n}" }
17
+ sequence(:author_name) { |n| "Author #{n}" }
18
+ sequence(:content) { |n| "Content #{n}" }
18
19
  end
19
20
 
20
21
  factory :widget do
21
- sequence(:w_id){ |n| n}
22
+ sequence(:w_id) { |n| n }
22
23
  end
23
24
 
24
- factory :topic_with_book, :parent=>:topic do |m|
25
+ factory :question do
26
+ sequence(:body) { |n| "Text #{n}" }
27
+
28
+ trait :with_rule do
29
+ after(:build) do |question|
30
+ question.build_rule(FactoryBot.attributes_for(:rule))
31
+ end
32
+ end
33
+ end
34
+
35
+ factory :rule do
36
+ sequence(:id) { |n| n }
37
+ sequence(:condition_text) { |n| "q_#{n}_#{n}" }
38
+ end
39
+
40
+ factory :topic_with_book, parent: :topic do
25
41
  after(:build) do |topic|
26
42
  2.times do
27
- book = topic.books.build(:title=>FactoryGirl.generate(:book_title), :author_name=>'Stephen King')
43
+ book = topic.books.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
28
44
  3.times do
29
- book.chapters.build(:title => FactoryGirl.generate(:chapter_title))
45
+ book.chapters.build(title: FactoryBot.generate(:chapter_title))
30
46
  end
31
47
 
32
48
  4.times do
33
- book.end_notes.build(:note => FactoryGirl.generate(:end_note))
49
+ book.end_notes.build(note: FactoryBot.generate(:end_note))
34
50
  end
35
51
  end
36
52
  end
37
53
  end
38
54
 
55
+ factory :book do
56
+ title { 'Tortilla Flat' }
57
+ author_name { 'John Steinbeck' }
58
+ end
59
+
60
+ factory :car do
61
+ sequence(:Name) { |n| n }
62
+ sequence(:Features) { |n| "Feature #{n}" }
63
+ end
39
64
  end
@@ -1,29 +1,29 @@
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
- factory_girl_args = args.shift || {}
5
+ factory_bot_args = args.shift || {}
6
6
 
7
7
  if n
8
- Array.new.tap do |collection|
9
- n.times.each { collection << FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args) }
8
+ [].tap do |collection|
9
+ n.times.each { collection << FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args) }
10
10
  end
11
11
  else
12
- FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args)
12
+ FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args)
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
- factory_girl_args = args.shift || {}
19
+ factory_bot_args = args.shift || {}
20
20
 
21
21
  if n
22
- Array.new.tap do |collection|
23
- n.times.each { collection << FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args) }
22
+ [].tap do |collection|
23
+ n.times.each { collection << FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args) }
24
24
  end
25
25
  else
26
- FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args)
26
+ FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args)
27
27
  end
28
28
  end
29
29
  end
@@ -1,147 +1,98 @@
1
1
  # encoding: UTF-8
2
2
  def should_support_mysql_import_functionality
3
3
  # Forcefully disable strict mode for this session.
4
- ActiveRecord::Base.connection.execute "set sql_mode=''"
4
+ ActiveRecord::Base.connection.execute "set sql_mode='STRICT_ALL_TABLES'"
5
5
 
6
- describe "#import with :on_duplicate_key_update option (mysql specific functionality)" do
7
- extend ActiveSupport::TestCase::MySQLAssertions
6
+ should_support_basic_on_duplicate_key_update
7
+ should_support_on_duplicate_key_ignore
8
8
 
9
- asssertion_group(:should_support_on_duplicate_key_update) do
10
- should_not_update_fields_not_mentioned
11
- should_update_foreign_keys
12
- should_not_update_created_at_on_timestamp_columns
13
- should_update_updated_at_on_timestamp_columns
14
- end
9
+ describe "#import" do
10
+ context "with :on_duplicate_key_update and validation checks turned off" do
11
+ extend ActiveSupport::TestCase::ImportAssertions
12
+
13
+ asssertion_group(:should_support_on_duplicate_key_update) do
14
+ should_not_update_fields_not_mentioned
15
+ should_update_foreign_keys
16
+ should_not_update_created_at_on_timestamp_columns
17
+ should_update_updated_at_on_timestamp_columns
18
+ end
15
19
 
16
- macro(:perform_import){ raise "supply your own #perform_import in a context below" }
17
- macro(:updated_topic){ Topic.find(@topic.id) }
20
+ macro(:perform_import) { raise "supply your own #perform_import in a context below" }
21
+ macro(:updated_topic) { Topic.find(@topic.id) }
18
22
 
19
- context "given columns and values with :validation checks turned off" do
20
- let(:columns){ %w( id title author_name author_email_address parent_id ) }
21
- let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
22
- let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
23
+ let(:columns) { %w( id title author_name author_email_address parent_id ) }
24
+ let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17]] }
25
+ let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57]] }
23
26
 
24
27
  macro(:perform_import) do |*opts|
25
- Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
28
+ Topic.import columns, updated_values, opts.extract_options!.merge(on_duplicate_key_update: update_columns, validate: false)
26
29
  end
27
30
 
28
31
  setup do
29
- Topic.import columns, values, :validate => false
32
+ Topic.import columns, values, validate: false
30
33
  @topic = Topic.find 99
31
34
  end
32
35
 
33
- context "using string column names" do
34
- let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
35
- should_support_on_duplicate_key_update
36
- should_update_fields_mentioned
37
- end
38
-
39
- context "using symbol column names" do
40
- let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
41
- should_support_on_duplicate_key_update
42
- should_update_fields_mentioned
43
- end
44
-
45
36
  context "using string hash map" do
46
- let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
37
+ let(:update_columns) { { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
47
38
  should_support_on_duplicate_key_update
48
39
  should_update_fields_mentioned
49
40
  end
50
41
 
51
42
  context "using string hash map, but specifying column mismatches" do
52
- let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
43
+ let(:update_columns) { { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
53
44
  should_support_on_duplicate_key_update
54
45
  should_update_fields_mentioned_with_hash_mappings
55
46
  end
56
47
 
57
48
  context "using symbol hash map" do
58
- let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
49
+ let(:update_columns) { { title: :title, author_email_address: :author_email_address, parent_id: :parent_id } }
59
50
  should_support_on_duplicate_key_update
60
51
  should_update_fields_mentioned
61
52
  end
62
53
 
63
54
  context "using symbol hash map, but specifying column mismatches" do
64
- let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
55
+ let(:update_columns) { { title: :author_email_address, author_email_address: :title, parent_id: :parent_id } }
65
56
  should_support_on_duplicate_key_update
66
57
  should_update_fields_mentioned_with_hash_mappings
67
58
  end
68
59
  end
69
60
 
70
- context "given array of model instances with :validation checks turned off" do
71
- macro(:perform_import) do |*opts|
72
- @topic.title = "Book - 2nd Edition"
73
- @topic.author_name = "Author Should Not Change"
74
- @topic.author_email_address = "johndoe@example.com"
75
- @topic.parent_id = 57
76
- Topic.import [@topic], opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
77
- end
61
+ context "with :synchronization option" do
62
+ let(:topics) { [] }
63
+ let(:values) { [[topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"]] }
64
+ let(:columns) { %w(id author_name title) }
78
65
 
79
66
  setup do
80
- @topic = Generate(:topic, :id => 99, :author_name => "John Doe", :parent_id => 17)
67
+ topics << Topic.create!(title: "LDAP", author_name: "Big Bird", content: "Putting Directories to Work.")
68
+ topics << Topic.create!(title: "Rails Recipes", author_name: "Elmo", content: "A trusted collection of solutions.")
81
69
  end
82
70
 
83
- context "using string column names" do
84
- let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
85
- should_support_on_duplicate_key_update
86
- should_update_fields_mentioned
87
- end
71
+ it "synchronizes passed in ActiveRecord model instances with the data just imported" do
72
+ columns2update = ['author_name']
88
73
 
89
- context "using symbol column names" do
90
- let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
91
- should_support_on_duplicate_key_update
92
- should_update_fields_mentioned
93
- end
74
+ expected_count = Topic.count
75
+ Topic.import( columns, values,
76
+ validate: false,
77
+ on_duplicate_key_update: columns2update,
78
+ synchronize: topics )
94
79
 
95
- context "using string hash map" do
96
- let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
97
- should_support_on_duplicate_key_update
98
- should_update_fields_mentioned
99
- end
100
-
101
- context "using string hash map, but specifying column mismatches" do
102
- let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
103
- should_support_on_duplicate_key_update
104
- should_update_fields_mentioned_with_hash_mappings
105
- end
106
-
107
- context "using symbol hash map" do
108
- let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
109
- should_support_on_duplicate_key_update
110
- should_update_fields_mentioned
111
- end
112
-
113
- context "using symbol hash map, but specifying column mismatches" do
114
- let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
115
- should_support_on_duplicate_key_update
116
- should_update_fields_mentioned_with_hash_mappings
80
+ assert_equal expected_count, Topic.count, "no new records should have been created!"
81
+ assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
82
+ assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
117
83
  end
118
84
  end
119
85
 
120
- end
121
-
122
- describe "#import with :synchronization option" do
123
- let(:topics){ Array.new }
124
- let(:values){ [ [topics.first.id, "Jerry Carter"], [topics.last.id, "Chad Fowler"] ]}
125
- let(:columns){ %W(id author_name) }
86
+ if ENV['AR_VERSION'].to_f >= 5.1
87
+ context "with virtual columns" do
88
+ let(:books) { [Book.new(author_name: "foo", title: "bar")] }
126
89
 
127
- setup do
128
- topics << Topic.create!(:title=>"LDAP", :author_name=>"Big Bird")
129
- topics << Topic.create!(:title=>"Rails Recipes", :author_name=>"Elmo")
130
- end
131
-
132
- it "synchronizes passed in ActiveRecord model instances with the data just imported" do
133
- columns2update = [ 'author_name' ]
134
-
135
- expected_count = Topic.count
136
- Topic.import( columns, values,
137
- :validate=>false,
138
- :on_duplicate_key_update=>columns2update,
139
- :synchronize=>topics )
140
-
141
- assert_equal expected_count, Topic.count, "no new records should have been created!"
142
- assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
143
- assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
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
144
96
  end
145
97
  end
146
-
147
98
  end