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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +49 -0
- data/.rubocop_todo.yml +36 -0
- data/.travis.yml +64 -8
- data/CHANGELOG.md +475 -0
- data/Gemfile +32 -15
- data/LICENSE +21 -56
- data/README.markdown +564 -35
- data/Rakefile +20 -3
- data/activerecord-import.gemspec +7 -7
- data/benchmarks/README +2 -2
- data/benchmarks/benchmark.rb +68 -64
- data/benchmarks/lib/base.rb +138 -137
- data/benchmarks/lib/cli_parser.rb +107 -103
- data/benchmarks/lib/{mysql_benchmark.rb → mysql2_benchmark.rb} +19 -22
- data/benchmarks/lib/output_to_csv.rb +5 -4
- data/benchmarks/lib/output_to_html.rb +8 -13
- data/benchmarks/models/test_innodb.rb +1 -1
- data/benchmarks/models/test_memory.rb +1 -1
- data/benchmarks/models/test_myisam.rb +1 -1
- data/benchmarks/schema/mysql2_schema.rb +16 -0
- data/gemfiles/3.2.gemfile +2 -4
- data/gemfiles/4.0.gemfile +2 -4
- data/gemfiles/4.1.gemfile +2 -4
- data/gemfiles/4.2.gemfile +2 -4
- data/gemfiles/5.0.gemfile +2 -0
- data/gemfiles/5.1.gemfile +2 -0
- data/gemfiles/5.2.gemfile +2 -0
- data/gemfiles/6.0.gemfile +2 -0
- data/gemfiles/6.1.gemfile +1 -0
- data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +6 -0
- data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
- data/lib/activerecord-import/adapters/abstract_adapter.rb +23 -17
- data/lib/activerecord-import/adapters/mysql_adapter.rb +52 -25
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +187 -10
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +148 -17
- data/lib/activerecord-import/base.rb +15 -9
- data/lib/activerecord-import/import.rb +740 -191
- data/lib/activerecord-import/synchronize.rb +21 -21
- data/lib/activerecord-import/value_sets_parser.rb +33 -8
- data/lib/activerecord-import/version.rb +1 -1
- data/lib/activerecord-import.rb +4 -15
- data/test/adapters/jdbcsqlite3.rb +1 -0
- data/test/adapters/makara_postgis.rb +1 -0
- data/test/adapters/mysql2_makara.rb +1 -0
- data/test/adapters/mysql2spatial.rb +1 -1
- data/test/adapters/postgis.rb +1 -1
- data/test/adapters/postgresql.rb +1 -1
- data/test/adapters/postgresql_makara.rb +1 -0
- data/test/adapters/spatialite.rb +1 -1
- data/test/adapters/sqlite3.rb +1 -1
- data/test/database.yml.sample +13 -18
- data/test/import_test.rb +608 -89
- data/test/jdbcmysql/import_test.rb +2 -3
- data/test/jdbcpostgresql/import_test.rb +0 -2
- data/test/jdbcsqlite3/import_test.rb +4 -0
- data/test/makara_postgis/import_test.rb +8 -0
- data/test/models/account.rb +3 -0
- data/test/models/alarm.rb +2 -0
- data/test/models/animal.rb +6 -0
- data/test/models/bike_maker.rb +7 -0
- data/test/models/book.rb +7 -6
- data/test/models/car.rb +3 -0
- data/test/models/chapter.rb +2 -2
- data/test/models/dictionary.rb +4 -0
- data/test/models/discount.rb +3 -0
- data/test/models/end_note.rb +2 -2
- data/test/models/promotion.rb +3 -0
- data/test/models/question.rb +3 -0
- data/test/models/rule.rb +3 -0
- data/test/models/tag.rb +4 -0
- data/test/models/topic.rb +17 -3
- data/test/models/user.rb +3 -0
- data/test/models/user_token.rb +4 -0
- data/test/models/vendor.rb +7 -0
- data/test/models/widget.rb +19 -2
- data/test/mysql2/import_test.rb +2 -3
- data/test/{em_mysql2 → mysql2_makara}/import_test.rb +1 -1
- data/test/mysqlspatial2/import_test.rb +2 -2
- data/test/postgis/import_test.rb +5 -1
- data/test/schema/generic_schema.rb +159 -85
- data/test/schema/jdbcpostgresql_schema.rb +1 -0
- data/test/schema/mysql2_schema.rb +19 -0
- data/test/schema/postgis_schema.rb +1 -0
- data/test/schema/postgresql_schema.rb +61 -0
- data/test/schema/sqlite3_schema.rb +13 -0
- data/test/sqlite3/import_test.rb +2 -50
- data/test/support/active_support/test_case_extensions.rb +21 -13
- data/test/support/{mysql/assertions.rb → assertions.rb} +20 -2
- data/test/support/factories.rb +39 -14
- data/test/support/generate.rb +10 -10
- data/test/support/mysql/import_examples.rb +49 -98
- data/test/support/postgresql/import_examples.rb +535 -57
- data/test/support/shared_examples/on_duplicate_key_ignore.rb +43 -0
- data/test/support/shared_examples/on_duplicate_key_update.rb +378 -0
- data/test/support/shared_examples/recursive_import.rb +225 -0
- data/test/support/sqlite3/import_examples.rb +231 -0
- data/test/synchronize_test.rb +10 -2
- data/test/test_helper.rb +36 -8
- data/test/travis/database.yml +26 -17
- data/test/value_sets_bytes_parser_test.rb +25 -17
- data/test/value_sets_records_parser_test.rb +6 -6
- metadata +86 -42
- data/benchmarks/boot.rb +0 -18
- data/benchmarks/schema/mysql_schema.rb +0 -16
- data/gemfiles/3.1.gemfile +0 -4
- data/lib/activerecord-import/active_record/adapters/em_mysql2_adapter.rb +0 -8
- data/lib/activerecord-import/active_record/adapters/mysql_adapter.rb +0 -6
- data/lib/activerecord-import/em_mysql2.rb +0 -7
- data/lib/activerecord-import/mysql.rb +0 -7
- data/test/adapters/em_mysql2.rb +0 -1
- data/test/adapters/mysql.rb +0 -1
- data/test/adapters/mysqlspatial.rb +0 -1
- data/test/mysql/import_test.rb +0 -6
- data/test/mysqlspatial/import_test.rb +0 -6
- data/test/schema/mysql_schema.rb +0 -18
- data/test/travis/build.sh +0 -30
data/test/sqlite3/import_test.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
55
|
+
klass.instance_eval(&blk)
|
|
46
56
|
end
|
|
47
|
-
|
|
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
|
|
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 :
|
|
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
|
data/test/support/factories.rb
CHANGED
|
@@ -1,39 +1,64 @@
|
|
|
1
|
-
|
|
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, :
|
|
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 :
|
|
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(:
|
|
43
|
+
book = topic.books.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
|
|
28
44
|
3.times do
|
|
29
|
-
book.chapters.build(:
|
|
45
|
+
book.chapters.build(title: FactoryBot.generate(:chapter_title))
|
|
30
46
|
end
|
|
31
47
|
|
|
32
48
|
4.times do
|
|
33
|
-
book.end_notes.build(:
|
|
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
|
data/test/support/generate.rb
CHANGED
|
@@ -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
|
-
|
|
5
|
+
factory_bot_args = args.shift || {}
|
|
6
6
|
|
|
7
7
|
if n
|
|
8
|
-
|
|
9
|
-
n.times.each { collection <<
|
|
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
|
-
|
|
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
|
-
|
|
19
|
+
factory_bot_args = args.shift || {}
|
|
20
20
|
|
|
21
21
|
if n
|
|
22
|
-
|
|
23
|
-
n.times.each { collection <<
|
|
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
|
-
|
|
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
|
-
|
|
7
|
-
|
|
6
|
+
should_support_basic_on_duplicate_key_update
|
|
7
|
+
should_support_on_duplicate_key_ignore
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
let(:
|
|
21
|
-
let(:
|
|
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(:
|
|
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, :
|
|
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){ { :
|
|
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){ { :
|
|
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 "
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|