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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/README.markdown +9 -9
- data/lib/activerecord-import/active_record/adapters/mysql2_proxy_adapter.rb +8 -0
- data/lib/activerecord-import/active_record/adapters/postgresql_proxy_adapter.rb +8 -0
- data/lib/activerecord-import/active_record/adapters/sqlite3_proxy_adapter.rb +8 -0
- data/lib/activerecord-import/active_record/adapters/trilogy_proxy_adapter.rb +8 -0
- data/lib/activerecord-import/adapters/active_record_proxy_adapter.rb +19 -0
- data/lib/activerecord-import/adapters/mysql2_proxy_adapter.rb +9 -0
- data/lib/activerecord-import/adapters/mysql_adapter.rb +10 -3
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +1 -1
- data/lib/activerecord-import/adapters/postgresql_proxy_adapter.rb +9 -0
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +1 -1
- data/lib/activerecord-import/adapters/sqlite3_proxy_adapter.rb +9 -0
- data/lib/activerecord-import/adapters/trilogy_proxy_adapter.rb +9 -0
- data/lib/activerecord-import/base.rb +2 -2
- data/lib/activerecord-import/import.rb +243 -211
- data/lib/activerecord-import/version.rb +1 -1
- metadata +13 -200
- data/.github/workflows/test.yaml +0 -161
- data/.gitignore +0 -37
- data/.rubocop.yml +0 -118
- data/.rubocop_todo.yml +0 -30
- data/Brewfile +0 -5
- data/Dockerfile +0 -23
- data/Gemfile +0 -63
- data/Rakefile +0 -73
- data/activerecord-import.gemspec +0 -28
- data/benchmarks/README +0 -32
- data/benchmarks/benchmark.rb +0 -72
- data/benchmarks/lib/base.rb +0 -143
- data/benchmarks/lib/cli_parser.rb +0 -111
- data/benchmarks/lib/float.rb +0 -17
- data/benchmarks/lib/mysql2_benchmark.rb +0 -21
- data/benchmarks/lib/output_to_csv.rb +0 -21
- data/benchmarks/lib/output_to_html.rb +0 -66
- data/benchmarks/models/test_innodb.rb +0 -5
- data/benchmarks/models/test_memory.rb +0 -5
- data/benchmarks/models/test_myisam.rb +0 -5
- data/benchmarks/schema/mysql2_schema.rb +0 -18
- data/docker-compose.yml +0 -34
- data/gemfiles/5.2.gemfile +0 -4
- data/gemfiles/6.0.gemfile +0 -4
- data/gemfiles/6.1.gemfile +0 -4
- data/gemfiles/7.0.gemfile +0 -4
- data/gemfiles/7.1.gemfile +0 -3
- data/gemfiles/7.2.gemfile +0 -3
- data/gemfiles/8.0.gemfile +0 -3
- data/test/adapters/jdbcmysql.rb +0 -3
- data/test/adapters/jdbcpostgresql.rb +0 -3
- data/test/adapters/jdbcsqlite3.rb +0 -3
- data/test/adapters/makara_postgis.rb +0 -3
- data/test/adapters/mysql2.rb +0 -3
- data/test/adapters/mysql2_makara.rb +0 -3
- data/test/adapters/mysql2_proxy.rb +0 -3
- data/test/adapters/mysql2spatial.rb +0 -3
- data/test/adapters/postgis.rb +0 -3
- data/test/adapters/postgresql.rb +0 -3
- data/test/adapters/postgresql_makara.rb +0 -3
- data/test/adapters/postgresql_proxy.rb +0 -3
- data/test/adapters/seamless_database_pool.rb +0 -3
- data/test/adapters/spatialite.rb +0 -3
- data/test/adapters/sqlite3.rb +0 -3
- data/test/adapters/trilogy.rb +0 -11
- data/test/database.yml.sample +0 -65
- data/test/github/database.yml +0 -78
- data/test/import_test.rb +0 -970
- data/test/jdbcmysql/import_test.rb +0 -7
- data/test/jdbcpostgresql/import_test.rb +0 -6
- data/test/jdbcsqlite3/import_test.rb +0 -6
- data/test/makara_postgis/import_test.rb +0 -10
- data/test/models/account.rb +0 -5
- data/test/models/alarm.rb +0 -4
- data/test/models/animal.rb +0 -8
- data/test/models/author.rb +0 -9
- data/test/models/bike_maker.rb +0 -10
- data/test/models/book.rb +0 -18
- data/test/models/car.rb +0 -5
- data/test/models/card.rb +0 -5
- data/test/models/chapter.rb +0 -6
- data/test/models/composite_book.rb +0 -19
- data/test/models/composite_chapter.rb +0 -12
- data/test/models/customer.rb +0 -18
- data/test/models/deck.rb +0 -8
- data/test/models/dictionary.rb +0 -6
- data/test/models/discount.rb +0 -5
- data/test/models/end_note.rb +0 -6
- data/test/models/group.rb +0 -5
- data/test/models/order.rb +0 -17
- data/test/models/playing_card.rb +0 -4
- data/test/models/promotion.rb +0 -5
- data/test/models/question.rb +0 -5
- data/test/models/rule.rb +0 -5
- data/test/models/tag.rb +0 -12
- data/test/models/tag_alias.rb +0 -11
- data/test/models/topic.rb +0 -31
- data/test/models/user.rb +0 -5
- data/test/models/user_token.rb +0 -6
- data/test/models/vendor.rb +0 -9
- data/test/models/widget.rb +0 -33
- data/test/mysql2/import_test.rb +0 -7
- data/test/mysql2_makara/import_test.rb +0 -8
- data/test/mysql2_proxy/import_test.rb +0 -6
- data/test/mysqlspatial2/import_test.rb +0 -8
- data/test/postgis/import_test.rb +0 -10
- data/test/postgresql/import_test.rb +0 -6
- data/test/postgresql_proxy/import_test.rb +0 -6
- data/test/schema/generic_schema.rb +0 -230
- data/test/schema/jdbcpostgresql_schema.rb +0 -3
- data/test/schema/mysql2_schema.rb +0 -21
- data/test/schema/postgis_schema.rb +0 -3
- data/test/schema/postgresql_schema.rb +0 -94
- data/test/schema/sqlite3_schema.rb +0 -15
- data/test/schema/version.rb +0 -12
- data/test/sqlite3/import_test.rb +0 -6
- data/test/support/active_support/test_case_extensions.rb +0 -73
- data/test/support/assertions.rb +0 -75
- data/test/support/factories.rb +0 -66
- data/test/support/generate.rb +0 -31
- data/test/support/mysql/import_examples.rb +0 -97
- data/test/support/postgresql/import_examples.rb +0 -642
- data/test/support/shared_examples/on_duplicate_key_ignore.rb +0 -45
- data/test/support/shared_examples/on_duplicate_key_update.rb +0 -437
- data/test/support/shared_examples/recursive_import.rb +0 -352
- data/test/support/sqlite3/import_examples.rb +0 -232
- data/test/synchronize_test.rb +0 -43
- data/test/test_helper.rb +0 -91
- data/test/trilogy/import_test.rb +0 -7
- data/test/value_sets_bytes_parser_test.rb +0 -106
- data/test/value_sets_records_parser_test.rb +0 -34
|
@@ -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,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
|
data/test/schema/version.rb
DELETED
|
@@ -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
|
data/test/sqlite3/import_test.rb
DELETED
|
@@ -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
|
data/test/support/assertions.rb
DELETED
|
@@ -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
|
data/test/support/factories.rb
DELETED
|
@@ -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
|
data/test/support/generate.rb
DELETED
|
@@ -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
|