activerecord-import-rails4 0.5.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 +7 -0
- data/.gitignore +31 -0
- data/Appraisals +9 -0
- data/Gemfile +25 -0
- data/README.markdown +24 -0
- data/Rakefile +52 -0
- data/activerecord-import-rails4.gemspec +24 -0
- data/benchmarks/README +32 -0
- data/benchmarks/benchmark.rb +64 -0
- data/benchmarks/boot.rb +18 -0
- data/benchmarks/lib/base.rb +137 -0
- data/benchmarks/lib/cli_parser.rb +103 -0
- data/benchmarks/lib/float.rb +15 -0
- data/benchmarks/lib/mysql_benchmark.rb +22 -0
- data/benchmarks/lib/output_to_csv.rb +18 -0
- data/benchmarks/lib/output_to_html.rb +69 -0
- data/benchmarks/models/test_innodb.rb +3 -0
- data/benchmarks/models/test_memory.rb +3 -0
- data/benchmarks/models/test_myisam.rb +3 -0
- data/benchmarks/schema/mysql_schema.rb +16 -0
- data/gemfiles/rails3.gemfile +18 -0
- data/gemfiles/rails4.gemfile +18 -0
- data/lib/activerecord-import-rails4.rb +16 -0
- data/lib/activerecord-import-rails4/active_record/adapters/abstract_adapter.rb +10 -0
- data/lib/activerecord-import-rails4/active_record/adapters/jdbcmysql_adapter.rb +6 -0
- data/lib/activerecord-import-rails4/active_record/adapters/mysql2_adapter.rb +6 -0
- data/lib/activerecord-import-rails4/active_record/adapters/mysql_adapter.rb +6 -0
- data/lib/activerecord-import-rails4/active_record/adapters/postgresql_adapter.rb +7 -0
- data/lib/activerecord-import-rails4/active_record/adapters/seamless_database_pool_adapter.rb +7 -0
- data/lib/activerecord-import-rails4/active_record/adapters/sqlite3_adapter.rb +7 -0
- data/lib/activerecord-import-rails4/adapters/abstract_adapter.rb +119 -0
- data/lib/activerecord-import-rails4/adapters/mysql2_adapter.rb +5 -0
- data/lib/activerecord-import-rails4/adapters/mysql_adapter.rb +55 -0
- data/lib/activerecord-import-rails4/adapters/postgresql_adapter.rb +7 -0
- data/lib/activerecord-import-rails4/adapters/sqlite3_adapter.rb +5 -0
- data/lib/activerecord-import-rails4/base.rb +34 -0
- data/lib/activerecord-import-rails4/import.rb +387 -0
- data/lib/activerecord-import-rails4/mysql.rb +8 -0
- data/lib/activerecord-import-rails4/mysql2.rb +8 -0
- data/lib/activerecord-import-rails4/postgresql.rb +8 -0
- data/lib/activerecord-import-rails4/sqlite3.rb +8 -0
- data/lib/activerecord-import-rails4/synchronize.rb +60 -0
- data/lib/activerecord-import-rails4/version.rb +5 -0
- data/test/active_record/connection_adapter_test.rb +62 -0
- data/test/adapters/jdbcmysql.rb +1 -0
- data/test/adapters/mysql.rb +1 -0
- data/test/adapters/mysql2.rb +1 -0
- data/test/adapters/mysql2spatial.rb +1 -0
- data/test/adapters/mysqlspatial.rb +1 -0
- data/test/adapters/postgis.rb +1 -0
- data/test/adapters/postgresql.rb +1 -0
- data/test/adapters/seamless_database_pool.rb +1 -0
- data/test/adapters/spatialite.rb +1 -0
- data/test/adapters/sqlite3.rb +1 -0
- data/test/import_test.rb +321 -0
- data/test/jdbcmysql/import_test.rb +6 -0
- data/test/models/book.rb +3 -0
- data/test/models/group.rb +3 -0
- data/test/models/topic.rb +7 -0
- data/test/models/widget.rb +3 -0
- data/test/mysql/import_test.rb +6 -0
- data/test/mysql2/import_test.rb +6 -0
- data/test/mysqlspatial/import_test.rb +6 -0
- data/test/mysqlspatial2/import_test.rb +6 -0
- data/test/postgis/import_test.rb +4 -0
- data/test/postgresql/import_test.rb +4 -0
- data/test/schema/generic_schema.rb +102 -0
- data/test/schema/mysql_schema.rb +17 -0
- data/test/schema/version.rb +10 -0
- data/test/support/active_support/test_case_extensions.rb +67 -0
- data/test/support/factories.rb +19 -0
- data/test/support/generate.rb +29 -0
- data/test/support/mysql/assertions.rb +55 -0
- data/test/support/mysql/import_examples.rb +190 -0
- data/test/support/postgresql/import_examples.rb +21 -0
- data/test/synchronize_test.rb +22 -0
- data/test/test_helper.rb +48 -0
- metadata +197 -0
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
|
+
|
6
|
+
should_support_mysql_import_functionality
|
data/test/models/book.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
class Topic < ActiveRecord::Base
|
2
|
+
validates_presence_of :author_name
|
3
|
+
has_many :books
|
4
|
+
belongs_to :parent, :class_name => "Topic"
|
5
|
+
|
6
|
+
composed_of :description, :mapping => [ %w(title title), %w(author_name author_name)], :allow_nil => true, :class_name => "TopicDescription"
|
7
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
|
+
|
6
|
+
should_support_mysql_import_functionality
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
|
+
|
6
|
+
should_support_mysql_import_functionality
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
|
+
|
6
|
+
should_support_mysql_import_functionality
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
|
+
|
6
|
+
should_support_mysql_import_functionality
|
@@ -0,0 +1,102 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
create_table :schema_info, :force=>true do |t|
|
4
|
+
t.column :version, :integer, :unique=>true
|
5
|
+
end
|
6
|
+
SchemaInfo.create :version=>SchemaInfo::VERSION
|
7
|
+
|
8
|
+
create_table :group, :force => true do |t|
|
9
|
+
t.column :order, :string
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :topics, :force=>true do |t|
|
14
|
+
t.column :title, :string, :null => false
|
15
|
+
t.column :author_name, :string
|
16
|
+
t.column :author_email_address, :string
|
17
|
+
t.column :written_on, :datetime
|
18
|
+
t.column :bonus_time, :time
|
19
|
+
t.column :last_read, :datetime
|
20
|
+
t.column :content, :text
|
21
|
+
t.column :approved, :boolean, :default=>'1'
|
22
|
+
t.column :replies_count, :integer
|
23
|
+
t.column :parent_id, :integer
|
24
|
+
t.column :type, :string
|
25
|
+
t.column :created_at, :datetime
|
26
|
+
t.column :created_on, :datetime
|
27
|
+
t.column :updated_at, :datetime
|
28
|
+
t.column :updated_on, :datetime
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :projects, :force=>true do |t|
|
32
|
+
t.column :name, :string
|
33
|
+
t.column :type, :string
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :developers, :force=>true do |t|
|
37
|
+
t.column :name, :string
|
38
|
+
t.column :salary, :integer, :default=>'70000'
|
39
|
+
t.column :created_at, :datetime
|
40
|
+
t.column :team_id, :integer
|
41
|
+
t.column :updated_at, :datetime
|
42
|
+
end
|
43
|
+
|
44
|
+
create_table :addresses, :force=>true do |t|
|
45
|
+
t.column :address, :string
|
46
|
+
t.column :city, :string
|
47
|
+
t.column :state, :string
|
48
|
+
t.column :zip, :string
|
49
|
+
t.column :developer_id, :integer
|
50
|
+
end
|
51
|
+
|
52
|
+
create_table :teams, :force=>true do |t|
|
53
|
+
t.column :name, :string
|
54
|
+
end
|
55
|
+
|
56
|
+
create_table :books, :force=>true do |t|
|
57
|
+
t.column :title, :string, :null=>false
|
58
|
+
t.column :publisher, :string, :null=>false, :default => 'Default Publisher'
|
59
|
+
t.column :author_name, :string, :null=>false
|
60
|
+
t.column :created_at, :datetime
|
61
|
+
t.column :created_on, :datetime
|
62
|
+
t.column :updated_at, :datetime
|
63
|
+
t.column :updated_on, :datetime
|
64
|
+
t.column :publish_date, :date
|
65
|
+
t.column :topic_id, :integer
|
66
|
+
t.column :for_sale, :boolean, :default => true
|
67
|
+
end
|
68
|
+
|
69
|
+
create_table :languages, :force=>true do |t|
|
70
|
+
t.column :name, :string
|
71
|
+
t.column :developer_id, :integer
|
72
|
+
end
|
73
|
+
|
74
|
+
create_table :shopping_carts, :force=>true do |t|
|
75
|
+
t.column :name, :string, :null => true
|
76
|
+
t.column :created_at, :datetime
|
77
|
+
t.column :updated_at, :datetime
|
78
|
+
end
|
79
|
+
|
80
|
+
create_table :cart_items, :force => true do |t|
|
81
|
+
t.column :shopping_cart_id, :string, :null => false
|
82
|
+
t.column :book_id, :string, :null => false
|
83
|
+
t.column :copies, :integer, :default => 1
|
84
|
+
t.column :created_at, :datetime
|
85
|
+
t.column :updated_at, :datetime
|
86
|
+
end
|
87
|
+
|
88
|
+
add_index :cart_items, [:shopping_cart_id, :book_id], :unique => true, :name => 'uk_shopping_cart_books'
|
89
|
+
|
90
|
+
create_table :animals, :force => true do |t|
|
91
|
+
t.column :name, :string, :null => false
|
92
|
+
t.column :size, :string, :default => nil
|
93
|
+
t.column :created_at, :datetime
|
94
|
+
t.column :updated_at, :datetime
|
95
|
+
end
|
96
|
+
|
97
|
+
add_index :animals, [:name], :unique => true, :name => 'uk_animals'
|
98
|
+
|
99
|
+
create_table :widgets, :id => false, :force => true do |t|
|
100
|
+
t.integer :w_id
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
create_table :books, :options=>'ENGINE=MyISAM', :force=>true do |t|
|
4
|
+
t.column :title, :string, :null=>false
|
5
|
+
t.column :publisher, :string, :null=>false, :default => 'Default Publisher'
|
6
|
+
t.column :author_name, :string, :null=>false
|
7
|
+
t.column :created_at, :datetime
|
8
|
+
t.column :created_on, :datetime
|
9
|
+
t.column :updated_at, :datetime
|
10
|
+
t.column :updated_on, :datetime
|
11
|
+
t.column :publish_date, :date
|
12
|
+
t.column :topic_id, :integer
|
13
|
+
t.column :for_sale, :boolean, :default => true
|
14
|
+
end
|
15
|
+
execute "ALTER TABLE books ADD FULLTEXT( `title`, `publisher`, `author_name` )"
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class SchemaInfo < ActiveRecord::Base
|
2
|
+
if respond_to?(:table_name=)
|
3
|
+
self.table_name = 'schema_info'
|
4
|
+
else
|
5
|
+
# this is becoming deprecated in ActiveRecord but not all adapters supported it
|
6
|
+
# at this time
|
7
|
+
set_table_name 'schema_info'
|
8
|
+
end
|
9
|
+
VERSION = 12
|
10
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class ActiveSupport::TestCase
|
2
|
+
include ActiveRecord::TestFixtures
|
3
|
+
self.use_transactional_fixtures = true
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def assertion(name, &block)
|
7
|
+
mc = class << self ; self ; end
|
8
|
+
mc.class_eval do
|
9
|
+
define_method(name) do
|
10
|
+
it(name, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def asssertion_group(name, &block)
|
16
|
+
mc = class << self ; self ; end
|
17
|
+
mc.class_eval do
|
18
|
+
define_method(name, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def macro(name, &block)
|
23
|
+
class_eval do
|
24
|
+
define_method(name, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def describe(description, toplevel=nil, &blk)
|
29
|
+
text = toplevel ? description : "#{name} #{description}"
|
30
|
+
klass = Class.new(self)
|
31
|
+
|
32
|
+
klass.class_eval <<-RUBY_EVAL
|
33
|
+
def self.name
|
34
|
+
"#{text}"
|
35
|
+
end
|
36
|
+
RUBY_EVAL
|
37
|
+
|
38
|
+
# do not inherit test methods from the superclass
|
39
|
+
klass.class_eval do
|
40
|
+
instance_methods.grep(/^test.+/) do |method|
|
41
|
+
undef_method method
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
klass.instance_eval &blk
|
46
|
+
end
|
47
|
+
alias_method :context, :describe
|
48
|
+
|
49
|
+
def let(name, &blk)
|
50
|
+
values = {}
|
51
|
+
define_method(name) do
|
52
|
+
return values[name] if values.has_key?(name)
|
53
|
+
values[name] = instance_eval(&blk)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def it(description, &blk)
|
58
|
+
define_method("test: #{name} #{description}", &blk)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def describe(description, &blk)
|
65
|
+
ActiveSupport::TestCase.describe(description, true, &blk)
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :group do
|
3
|
+
sequence(:order) { |n| "Order #{n}" }
|
4
|
+
end
|
5
|
+
|
6
|
+
factory :invalid_topic, :class => "Topic" do
|
7
|
+
sequence(:title){ |n| "Title #{n}"}
|
8
|
+
author_name nil
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :topic do
|
12
|
+
sequence(:title){ |n| "Title #{n}"}
|
13
|
+
sequence(:author_name){ |n| "Author #{n}"}
|
14
|
+
end
|
15
|
+
|
16
|
+
factory :widget do
|
17
|
+
sequence(:w_id){ |n| n}
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ActiveSupport::TestCase
|
2
|
+
def Build(*args)
|
3
|
+
n = args.shift if args.first.is_a?(Numeric)
|
4
|
+
factory = args.shift
|
5
|
+
factory_girl_args = args.shift || {}
|
6
|
+
|
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) }
|
10
|
+
end
|
11
|
+
else
|
12
|
+
FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def Generate(*args)
|
17
|
+
n = args.shift if args.first.is_a?(Numeric)
|
18
|
+
factory = args.shift
|
19
|
+
factory_girl_args = args.shift || {}
|
20
|
+
|
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) }
|
24
|
+
end
|
25
|
+
else
|
26
|
+
FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class ActiveSupport::TestCase
|
2
|
+
module MySQLAssertions
|
3
|
+
def self.extended(klass)
|
4
|
+
klass.instance_eval do
|
5
|
+
assertion(:should_not_update_created_at_on_timestamp_columns) do
|
6
|
+
Delorean.time_travel_to("5 minutes from now") do
|
7
|
+
perform_import
|
8
|
+
assert_equal @topic.created_at.to_i, updated_topic.created_at.to_i
|
9
|
+
assert_equal @topic.created_on.to_i, updated_topic.created_on.to_i
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
assertion(:should_update_updated_at_on_timestamp_columns) do
|
14
|
+
time = Chronic.parse("5 minutes from now")
|
15
|
+
Delorean.time_travel_to(time) do
|
16
|
+
perform_import
|
17
|
+
assert_equal time.to_i, updated_topic.updated_at.to_i
|
18
|
+
assert_equal time.to_i, updated_topic.updated_on.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
assertion(:should_not_update_timestamps) do
|
23
|
+
Delorean.time_travel_to("5 minutes from now") do
|
24
|
+
perform_import :timestamps => false
|
25
|
+
assert_equal @topic.created_at.to_i, updated_topic.created_at.to_i
|
26
|
+
assert_equal @topic.created_on.to_i, updated_topic.created_on.to_i
|
27
|
+
assert_equal @topic.updated_at.to_i, updated_topic.updated_at.to_i
|
28
|
+
assert_equal @topic.updated_on.to_i, updated_topic.updated_on.to_i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
assertion(:should_not_update_fields_not_mentioned) do
|
33
|
+
assert_equal "John Doe", updated_topic.author_name
|
34
|
+
end
|
35
|
+
|
36
|
+
assertion(:should_update_fields_mentioned) do
|
37
|
+
perform_import
|
38
|
+
assert_equal "Book - 2nd Edition", updated_topic.title
|
39
|
+
assert_equal "johndoe@example.com", updated_topic.author_email_address
|
40
|
+
end
|
41
|
+
|
42
|
+
assertion(:should_update_fields_mentioned_with_hash_mappings) do
|
43
|
+
perform_import
|
44
|
+
assert_equal "johndoe@example.com", updated_topic.title
|
45
|
+
assert_equal "Book - 2nd Edition", updated_topic.author_email_address
|
46
|
+
end
|
47
|
+
|
48
|
+
assertion(:should_update_foreign_keys) do
|
49
|
+
perform_import
|
50
|
+
assert_equal 57, updated_topic.parent_id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
def should_support_mysql_import_functionality
|
3
|
+
|
4
|
+
describe "building insert value sets" do
|
5
|
+
it "should properly build insert value set based on max packet allowed" do
|
6
|
+
values = [
|
7
|
+
"('1','2','3')",
|
8
|
+
"('4','5','6')",
|
9
|
+
"('7','8','9')" ]
|
10
|
+
|
11
|
+
adapter = ActiveRecord::Base.connection.class
|
12
|
+
values_size_in_bytes = values.sum {|value| value.bytesize }
|
13
|
+
base_sql_size_in_bytes = 15
|
14
|
+
max_bytes = 30
|
15
|
+
|
16
|
+
value_sets = adapter.get_insert_value_sets( values, base_sql_size_in_bytes, max_bytes )
|
17
|
+
assert_equal 3, value_sets.size, 'Three value sets were expected!'
|
18
|
+
|
19
|
+
# Each element in the value_sets array must be an array
|
20
|
+
value_sets.each_with_index { |e,i|
|
21
|
+
assert_kind_of Array, e, "Element #{i} was expected to be an Array!" }
|
22
|
+
|
23
|
+
# Each element in the values array should have a 1:1 correlation to the elements
|
24
|
+
# in the returned value_sets arrays
|
25
|
+
assert_equal values[0], value_sets[0].first
|
26
|
+
assert_equal values[1], value_sets[1].first
|
27
|
+
assert_equal values[2], value_sets[2].first
|
28
|
+
end
|
29
|
+
|
30
|
+
context "data contains multi-byte chars" do
|
31
|
+
it "should properly build insert value set based on max packet allowed" do
|
32
|
+
# each accented e should be 2 bytes, so each entry is 6 bytes instead of 5
|
33
|
+
values = [
|
34
|
+
"('é')",
|
35
|
+
"('é')" ]
|
36
|
+
|
37
|
+
adapter = ActiveRecord::Base.connection.class
|
38
|
+
base_sql_size_in_bytes = 15
|
39
|
+
max_bytes = 26
|
40
|
+
|
41
|
+
values_size_in_bytes = values.sum {|value| value.bytesize }
|
42
|
+
value_sets = adapter.get_insert_value_sets( values, base_sql_size_in_bytes, max_bytes )
|
43
|
+
|
44
|
+
assert_equal 2, value_sets.size, 'Two value sets were expected!'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#import with :on_duplicate_key_update option (mysql specific functionality)" do
|
50
|
+
extend ActiveSupport::TestCase::MySQLAssertions
|
51
|
+
|
52
|
+
asssertion_group(:should_support_on_duplicate_key_update) do
|
53
|
+
should_not_update_fields_not_mentioned
|
54
|
+
should_update_foreign_keys
|
55
|
+
should_not_update_created_at_on_timestamp_columns
|
56
|
+
should_update_updated_at_on_timestamp_columns
|
57
|
+
end
|
58
|
+
|
59
|
+
macro(:perform_import){ raise "supply your own #perform_import in a context below" }
|
60
|
+
macro(:updated_topic){ Topic.find(@topic) }
|
61
|
+
|
62
|
+
context "given columns and values with :validation checks turned off" do
|
63
|
+
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
64
|
+
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
65
|
+
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
66
|
+
|
67
|
+
macro(:perform_import) do |*opts|
|
68
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
69
|
+
end
|
70
|
+
|
71
|
+
setup do
|
72
|
+
Topic.import columns, values, :validate => false
|
73
|
+
@topic = Topic.find 99
|
74
|
+
end
|
75
|
+
|
76
|
+
context "using string column names" do
|
77
|
+
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
78
|
+
should_support_on_duplicate_key_update
|
79
|
+
should_update_fields_mentioned
|
80
|
+
end
|
81
|
+
|
82
|
+
context "using symbol column names" do
|
83
|
+
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
84
|
+
should_support_on_duplicate_key_update
|
85
|
+
should_update_fields_mentioned
|
86
|
+
end
|
87
|
+
|
88
|
+
context "using string hash map" do
|
89
|
+
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
90
|
+
should_support_on_duplicate_key_update
|
91
|
+
should_update_fields_mentioned
|
92
|
+
end
|
93
|
+
|
94
|
+
context "using string hash map, but specifying column mismatches" do
|
95
|
+
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
96
|
+
should_support_on_duplicate_key_update
|
97
|
+
should_update_fields_mentioned_with_hash_mappings
|
98
|
+
end
|
99
|
+
|
100
|
+
context "using symbol hash map" do
|
101
|
+
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
102
|
+
should_support_on_duplicate_key_update
|
103
|
+
should_update_fields_mentioned
|
104
|
+
end
|
105
|
+
|
106
|
+
context "using symbol hash map, but specifying column mismatches" do
|
107
|
+
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
108
|
+
should_support_on_duplicate_key_update
|
109
|
+
should_update_fields_mentioned_with_hash_mappings
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "given array of model instances with :validation checks turned off" do
|
114
|
+
macro(:perform_import) do |*opts|
|
115
|
+
@topic.title = "Book - 2nd Edition"
|
116
|
+
@topic.author_name = "Author Should Not Change"
|
117
|
+
@topic.author_email_address = "johndoe@example.com"
|
118
|
+
@topic.parent_id = 57
|
119
|
+
Topic.import [@topic], opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
120
|
+
end
|
121
|
+
|
122
|
+
setup do
|
123
|
+
@topic = Generate(:topic, :id => 99, :author_name => "John Doe", :parent_id => 17)
|
124
|
+
end
|
125
|
+
|
126
|
+
context "using string column names" do
|
127
|
+
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
128
|
+
should_support_on_duplicate_key_update
|
129
|
+
should_update_fields_mentioned
|
130
|
+
end
|
131
|
+
|
132
|
+
context "using symbol column names" do
|
133
|
+
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
134
|
+
should_support_on_duplicate_key_update
|
135
|
+
should_update_fields_mentioned
|
136
|
+
end
|
137
|
+
|
138
|
+
context "using string hash map" do
|
139
|
+
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
140
|
+
should_support_on_duplicate_key_update
|
141
|
+
should_update_fields_mentioned
|
142
|
+
end
|
143
|
+
|
144
|
+
context "using string hash map, but specifying column mismatches" do
|
145
|
+
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
146
|
+
should_support_on_duplicate_key_update
|
147
|
+
should_update_fields_mentioned_with_hash_mappings
|
148
|
+
end
|
149
|
+
|
150
|
+
context "using symbol hash map" do
|
151
|
+
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
152
|
+
should_support_on_duplicate_key_update
|
153
|
+
should_update_fields_mentioned
|
154
|
+
end
|
155
|
+
|
156
|
+
context "using symbol hash map, but specifying column mismatches" do
|
157
|
+
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
158
|
+
should_support_on_duplicate_key_update
|
159
|
+
should_update_fields_mentioned_with_hash_mappings
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "#import with :synchronization option" do
|
166
|
+
let(:topics){ Array.new }
|
167
|
+
let(:values){ [ [topics.first.id, "Jerry Carter"], [topics.last.id, "Chad Fowler"] ]}
|
168
|
+
let(:columns){ %W(id author_name) }
|
169
|
+
|
170
|
+
setup do
|
171
|
+
topics << Topic.create!(:title=>"LDAP", :author_name=>"Big Bird")
|
172
|
+
topics << Topic.create!(:title=>"Rails Recipes", :author_name=>"Elmo")
|
173
|
+
end
|
174
|
+
|
175
|
+
it "synchronizes passed in ActiveRecord model instances with the data just imported" do
|
176
|
+
columns2update = [ 'author_name' ]
|
177
|
+
|
178
|
+
expected_count = Topic.count
|
179
|
+
Topic.import( columns, values,
|
180
|
+
:validate=>false,
|
181
|
+
:on_duplicate_key_update=>columns2update,
|
182
|
+
:synchronize=>topics )
|
183
|
+
|
184
|
+
assert_equal expected_count, Topic.count, "no new records should have been created!"
|
185
|
+
assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
|
186
|
+
assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|