activerecord-import 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/Gemfile +4 -2
- data/README.markdown +8 -7
- data/Rakefile +1 -1
- data/benchmarks/benchmark.rb +2 -1
- data/benchmarks/lib/cli_parser.rb +1 -1
- data/benchmarks/lib/{mysql_benchmark.rb → mysql2_benchmark.rb} +6 -7
- data/gemfiles/3.1.gemfile +0 -2
- data/gemfiles/3.2.gemfile +0 -2
- data/gemfiles/4.0.gemfile +0 -2
- data/gemfiles/4.1.gemfile +0 -2
- data/gemfiles/4.2.gemfile +0 -2
- data/gemfiles/5.0.gemfile +0 -2
- data/lib/activerecord-import/adapters/abstract_adapter.rb +11 -2
- data/lib/activerecord-import/adapters/mysql_adapter.rb +14 -2
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +105 -1
- data/lib/activerecord-import/base.rb +0 -1
- data/lib/activerecord-import/import.rb +92 -21
- data/lib/activerecord-import/version.rb +1 -1
- data/test/database.yml.sample +0 -12
- data/test/import_test.rb +1 -1
- data/test/jdbcmysql/import_test.rb +2 -2
- data/test/jdbcpostgresql/import_test.rb +0 -1
- data/test/models/book.rb +4 -4
- data/test/models/promotion.rb +3 -0
- data/test/models/question.rb +3 -0
- data/test/models/rule.rb +3 -0
- data/test/models/topic.rb +1 -1
- data/test/mysql2/import_test.rb +2 -3
- data/test/mysqlspatial2/import_test.rb +2 -2
- data/test/postgresql/import_test.rb +4 -0
- data/test/schema/generic_schema.rb +19 -2
- data/test/support/{mysql/assertions.rb → assertions.rb} +12 -3
- data/test/support/factories.rb +14 -0
- data/test/support/mysql/import_examples.rb +28 -119
- data/test/support/postgresql/import_examples.rb +156 -1
- data/test/support/shared_examples/on_duplicate_key_update.rb +92 -0
- data/test/test_helper.rb +5 -1
- data/test/travis/build.sh +12 -8
- data/test/travis/database.yml +0 -12
- metadata +14 -23
- 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/em_mysql2/import_test.rb +0 -6
- data/test/mysql/import_test.rb +0 -6
- data/test/mysqlspatial/import_test.rb +0 -6
- data/test/support/em-synchrony_extensions.rb +0 -13
data/test/database.yml.sample
CHANGED
@@ -5,25 +5,13 @@ common: &common
|
|
5
5
|
host: localhost
|
6
6
|
database: activerecord_import_test
|
7
7
|
|
8
|
-
mysql: &mysql
|
9
|
-
<<: *common
|
10
|
-
adapter: mysql
|
11
|
-
|
12
8
|
mysql2: &mysql2
|
13
9
|
<<: *common
|
14
10
|
adapter: mysql2
|
15
11
|
|
16
|
-
mysqlspatial:
|
17
|
-
<<: *mysql
|
18
|
-
|
19
12
|
mysql2spatial:
|
20
13
|
<<: *mysql2
|
21
14
|
|
22
|
-
em_mysql2:
|
23
|
-
<<: *common
|
24
|
-
adapter: em_mysql2
|
25
|
-
pool: 5
|
26
|
-
|
27
15
|
seamless_database_pool:
|
28
16
|
<<: *common
|
29
17
|
adapter: seamless_database_pool
|
data/test/import_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../support/
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/assertions')
|
4
4
|
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
5
|
|
6
|
-
should_support_mysql_import_functionality
|
6
|
+
should_support_mysql_import_functionality
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
2
|
|
3
|
-
#require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/assertions')
|
4
3
|
require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples')
|
5
4
|
|
6
5
|
should_support_postgresql_import_functionality
|
data/test/models/book.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class Book < ActiveRecord::Base
|
2
|
-
belongs_to :topic, :inverse_of
|
3
|
-
has_many :chapters, :
|
4
|
-
has_many :end_notes, :
|
5
|
-
if ENV['AR_VERSION'].
|
2
|
+
belongs_to :topic, :inverse_of => :books
|
3
|
+
has_many :chapters, :inverse_of => :book
|
4
|
+
has_many :end_notes, :inverse_of => :book
|
5
|
+
if ENV['AR_VERSION'].to_f >= 4.1
|
6
6
|
enum status: [:draft, :published]
|
7
7
|
end
|
8
8
|
end
|
data/test/models/rule.rb
ADDED
data/test/models/topic.rb
CHANGED
@@ -2,7 +2,7 @@ class Topic < ActiveRecord::Base
|
|
2
2
|
validates_presence_of :author_name
|
3
3
|
validates :title, numericality: { only_integer: true }, on: :context_test
|
4
4
|
|
5
|
-
has_many :books, :
|
5
|
+
has_many :books, :inverse_of => :topic
|
6
6
|
belongs_to :parent, :class_name => "Topic"
|
7
7
|
|
8
8
|
composed_of :description, :mapping => [ %w(title title), %w(author_name author_name)], :allow_nil => true, :class_name => "TopicDescription"
|
data/test/mysql2/import_test.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
-
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/assertions')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/assertions')
|
4
3
|
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
4
|
|
6
|
-
should_support_mysql_import_functionality
|
5
|
+
should_support_mysql_import_functionality
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../support/
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../support/assertions')
|
4
4
|
require File.expand_path(File.dirname(__FILE__) + '/../support/mysql/import_examples')
|
5
5
|
|
6
|
-
should_support_mysql_import_functionality
|
6
|
+
should_support_mysql_import_functionality
|
@@ -2,3 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples')
|
3
3
|
|
4
4
|
should_support_postgresql_import_functionality
|
5
|
+
|
6
|
+
if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
|
7
|
+
should_support_postgresql_upsert_functionality
|
8
|
+
end
|
@@ -7,7 +7,7 @@ ActiveRecord::Schema.define do
|
|
7
7
|
|
8
8
|
create_table :group, :force => true do |t|
|
9
9
|
t.column :order, :string
|
10
|
-
t.timestamps
|
10
|
+
t.timestamps null: true
|
11
11
|
end
|
12
12
|
|
13
13
|
create_table :topics, :force=>true do |t|
|
@@ -64,7 +64,7 @@ ActiveRecord::Schema.define do
|
|
64
64
|
t.column :publish_date, :date
|
65
65
|
t.column :topic_id, :integer
|
66
66
|
t.column :for_sale, :boolean, :default => true
|
67
|
-
t.column :status, :integer
|
67
|
+
t.column :status, :integer, :default => 0
|
68
68
|
end
|
69
69
|
|
70
70
|
create_table :chapters, :force => true do |t|
|
@@ -118,4 +118,21 @@ ActiveRecord::Schema.define do
|
|
118
118
|
t.text :data
|
119
119
|
t.text :json_data
|
120
120
|
end
|
121
|
+
|
122
|
+
create_table "promotions", primary_key: "promotion_id", force: :cascade do |t|
|
123
|
+
t.string :code
|
124
|
+
t.string :description
|
125
|
+
t.decimal :discount
|
126
|
+
end
|
127
|
+
|
128
|
+
add_index :promotions, [:code], :unique => true, :name => 'uk_code'
|
129
|
+
|
130
|
+
create_table :rules, force: true do |t|
|
131
|
+
t.column :condition_text, :string
|
132
|
+
t.column :question_id, :integer
|
133
|
+
end
|
134
|
+
|
135
|
+
create_table :questions, force: true do |t|
|
136
|
+
t.column :body, :string
|
137
|
+
end
|
121
138
|
end
|
@@ -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,6 +19,15 @@ 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
33
|
perform_import :timestamps => false
|
@@ -40,10 +49,10 @@ class ActiveSupport::TestCase
|
|
40
49
|
end
|
41
50
|
|
42
51
|
assertion(:should_raise_update_fields_mentioned) do
|
43
|
-
assert_raise ActiveRecord::RecordNotUnique do
|
52
|
+
assert_raise ActiveRecord::RecordNotUnique do
|
44
53
|
perform_import
|
45
54
|
end
|
46
|
-
|
55
|
+
|
47
56
|
assert_equal "Book", updated_topic.title
|
48
57
|
assert_equal "john@doe.com", updated_topic.author_email_address
|
49
58
|
end
|
data/test/support/factories.rb
CHANGED
@@ -21,6 +21,20 @@ FactoryGirl.define do
|
|
21
21
|
sequence(:w_id){ |n| n}
|
22
22
|
end
|
23
23
|
|
24
|
+
factory :question do
|
25
|
+
sequence(:body) { |n| "Text #{n}"}
|
26
|
+
|
27
|
+
trait :with_rule do
|
28
|
+
after(:build) do |question|
|
29
|
+
question.build_rule(FactoryGirl.attributes_for(:rule))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
factory :rule do
|
35
|
+
sequence(:condition_text){ |n| "q_#{n}_#{n}"}
|
36
|
+
end
|
37
|
+
|
24
38
|
factory :topic_with_book, :parent=>:topic do |m|
|
25
39
|
after(:build) do |topic|
|
26
40
|
2.times do
|
@@ -3,29 +3,22 @@ def should_support_mysql_import_functionality
|
|
3
3
|
# Forcefully disable strict mode for this session.
|
4
4
|
ActiveRecord::Base.connection.execute "set sql_mode='STRICT_ALL_TABLES'"
|
5
5
|
|
6
|
-
|
7
|
-
extend ActiveSupport::TestCase::MySQLAssertions
|
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
|
6
|
+
should_support_basic_on_duplicate_key_update
|
15
7
|
|
16
|
-
|
17
|
-
|
8
|
+
describe "#import" do
|
9
|
+
context "with :on_duplicate_key_update and validation checks turned off" do
|
10
|
+
extend ActiveSupport::TestCase::ImportAssertions
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
12
|
+
asssertion_group(:should_support_on_duplicate_key_update) do
|
13
|
+
should_not_update_fields_not_mentioned
|
14
|
+
should_update_foreign_keys
|
15
|
+
should_not_update_created_at_on_timestamp_columns
|
16
|
+
should_update_updated_at_on_timestamp_columns
|
25
17
|
end
|
26
|
-
end
|
27
18
|
|
28
|
-
|
19
|
+
macro(:perform_import){ raise "supply your own #perform_import in a context below" }
|
20
|
+
macro(:updated_topic){ Topic.find(@topic.id) }
|
21
|
+
|
29
22
|
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
30
23
|
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
31
24
|
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
@@ -39,18 +32,6 @@ def should_support_mysql_import_functionality
|
|
39
32
|
@topic = Topic.find 99
|
40
33
|
end
|
41
34
|
|
42
|
-
context "using string column names" do
|
43
|
-
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
44
|
-
should_support_on_duplicate_key_update
|
45
|
-
should_update_fields_mentioned
|
46
|
-
end
|
47
|
-
|
48
|
-
context "using symbol column names" do
|
49
|
-
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
50
|
-
should_support_on_duplicate_key_update
|
51
|
-
should_update_fields_mentioned
|
52
|
-
end
|
53
|
-
|
54
35
|
context "using string hash map" do
|
55
36
|
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
56
37
|
should_support_on_duplicate_key_update
|
@@ -76,101 +57,29 @@ def should_support_mysql_import_functionality
|
|
76
57
|
end
|
77
58
|
end
|
78
59
|
|
79
|
-
context "
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
@topic.author_email_address = "johndoe@example.com"
|
84
|
-
@topic.parent_id = 57
|
85
|
-
Topic.import [@topic], opts.extract_options!.merge(:on_duplicate_key_update => update_columns, :validate => false)
|
86
|
-
end
|
60
|
+
context "with :synchronization option" do
|
61
|
+
let(:topics){ Array.new }
|
62
|
+
let(:values){ [ [topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"] ]}
|
63
|
+
let(:columns){ %W(id author_name title) }
|
87
64
|
|
88
65
|
setup do
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
context "using string column names" do
|
93
|
-
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
94
|
-
should_support_on_duplicate_key_update
|
95
|
-
should_update_fields_mentioned
|
96
|
-
end
|
97
|
-
|
98
|
-
context "using symbol column names" do
|
99
|
-
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
100
|
-
should_support_on_duplicate_key_update
|
101
|
-
should_update_fields_mentioned
|
102
|
-
end
|
103
|
-
|
104
|
-
context "using string hash map" do
|
105
|
-
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
106
|
-
should_support_on_duplicate_key_update
|
107
|
-
should_update_fields_mentioned
|
108
|
-
end
|
109
|
-
|
110
|
-
context "using string hash map, but specifying column mismatches" do
|
111
|
-
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
112
|
-
should_support_on_duplicate_key_update
|
113
|
-
should_update_fields_mentioned_with_hash_mappings
|
66
|
+
topics << Topic.create!(:title=>"LDAP", :author_name=>"Big Bird")
|
67
|
+
topics << Topic.create!(:title=>"Rails Recipes", :author_name=>"Elmo")
|
114
68
|
end
|
115
69
|
|
116
|
-
|
117
|
-
|
118
|
-
should_support_on_duplicate_key_update
|
119
|
-
should_update_fields_mentioned
|
120
|
-
end
|
121
|
-
|
122
|
-
context "using symbol hash map, but specifying column mismatches" do
|
123
|
-
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
124
|
-
should_support_on_duplicate_key_update
|
125
|
-
should_update_fields_mentioned_with_hash_mappings
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
context "given array of model instances with :on_duplicate_key_update turned off" do
|
130
|
-
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
131
|
-
let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
132
|
-
let(:updated_values){ [ [ 100, "Book - 2nd Edition", "This should raise an exception", "john@nogo.com", 57 ] ] }
|
70
|
+
it "synchronizes passed in ActiveRecord model instances with the data just imported" do
|
71
|
+
columns2update = [ 'author_name' ]
|
133
72
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
73
|
+
expected_count = Topic.count
|
74
|
+
Topic.import( columns, values,
|
75
|
+
:validate=>false,
|
76
|
+
:on_duplicate_key_update=>columns2update,
|
77
|
+
:synchronize=>topics )
|
138
78
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
context "using string column names" do
|
145
|
-
let(:update_columns){ [ "title", "author_email_address", "parent_id" ] }
|
146
|
-
should_raise_update_fields_mentioned
|
79
|
+
assert_equal expected_count, Topic.count, "no new records should have been created!"
|
80
|
+
assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
|
81
|
+
assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
|
147
82
|
end
|
148
83
|
end
|
149
84
|
end
|
150
|
-
|
151
|
-
describe "#import with :synchronization option" do
|
152
|
-
let(:topics){ Array.new }
|
153
|
-
let(:values){ [ [topics.first.id, "Jerry Carter", "title1"], [topics.last.id, "Chad Fowler", "title2"] ]}
|
154
|
-
let(:columns){ %W(id author_name title) }
|
155
|
-
|
156
|
-
setup do
|
157
|
-
topics << Topic.create!(:title=>"LDAP", :author_name=>"Big Bird")
|
158
|
-
topics << Topic.create!(:title=>"Rails Recipes", :author_name=>"Elmo")
|
159
|
-
end
|
160
|
-
|
161
|
-
it "synchronizes passed in ActiveRecord model instances with the data just imported" do
|
162
|
-
columns2update = [ 'author_name' ]
|
163
|
-
|
164
|
-
expected_count = Topic.count
|
165
|
-
Topic.import( columns, values,
|
166
|
-
:validate=>false,
|
167
|
-
:on_duplicate_key_update=>columns2update,
|
168
|
-
:synchronize=>topics )
|
169
|
-
|
170
|
-
assert_equal expected_count, Topic.count, "no new records should have been created!"
|
171
|
-
assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
|
172
|
-
assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
85
|
end
|
@@ -19,7 +19,6 @@ def should_support_postgresql_import_functionality
|
|
19
19
|
end
|
20
20
|
|
21
21
|
describe "importing objects with associations" do
|
22
|
-
|
23
22
|
let(:new_topics) { Build(num_topics, :topic_with_book) }
|
24
23
|
let(:new_topics_with_invalid_chapter) {
|
25
24
|
chapter = new_topics.first.books.first.chapters.first
|
@@ -31,6 +30,8 @@ def should_support_postgresql_import_functionality
|
|
31
30
|
let(:num_chapters) {18}
|
32
31
|
let(:num_endnotes) {24}
|
33
32
|
|
33
|
+
let(:new_question_with_rule) { FactoryGirl.build :question, :with_rule }
|
34
|
+
|
34
35
|
it 'imports top level' do
|
35
36
|
assert_difference "Topic.count", +num_topics do
|
36
37
|
Topic.import new_topics, :recursive => true
|
@@ -83,6 +84,12 @@ def should_support_postgresql_import_functionality
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
87
|
+
it 'imports has_one associations' do
|
88
|
+
assert_difference 'Rule.count' do
|
89
|
+
Question.import [new_question_with_rule], recursive: true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
86
93
|
# These models dont validate associated. So we expect that books and topics get inserted, but not chapters
|
87
94
|
# Putting a transaction around everything wouldn't work, so if you want your chapters to prevent topics from
|
88
95
|
# being created, you would need to have validates_associated in your models and insert with validation
|
@@ -127,3 +134,151 @@ def should_support_postgresql_import_functionality
|
|
127
134
|
end
|
128
135
|
end
|
129
136
|
end
|
137
|
+
|
138
|
+
def should_support_postgresql_upsert_functionality
|
139
|
+
should_support_basic_on_duplicate_key_update
|
140
|
+
|
141
|
+
describe "#import" do
|
142
|
+
extend ActiveSupport::TestCase::ImportAssertions
|
143
|
+
|
144
|
+
macro(:perform_import){ raise "supply your own #perform_import in a context below" }
|
145
|
+
macro(:updated_topic){ Topic.find(@topic.id) }
|
146
|
+
|
147
|
+
context "with :on_duplicate_key_ignore and validation checks turned off" do
|
148
|
+
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
149
|
+
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
150
|
+
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
151
|
+
|
152
|
+
macro(:perform_import) do |*opts|
|
153
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_ignore => value, :validate => false)
|
154
|
+
end
|
155
|
+
|
156
|
+
setup do
|
157
|
+
Topic.import columns, values, :validate => false
|
158
|
+
@topic = Topic.find 99
|
159
|
+
end
|
160
|
+
|
161
|
+
context "using true" do
|
162
|
+
let(:value){ true }
|
163
|
+
should_not_update_updated_at_on_timestamp_columns
|
164
|
+
end
|
165
|
+
|
166
|
+
context "using hash with :conflict_target" do
|
167
|
+
let(:value){ { conflict_target: :id } }
|
168
|
+
should_not_update_updated_at_on_timestamp_columns
|
169
|
+
end
|
170
|
+
|
171
|
+
context "using hash with :constraint_target" do
|
172
|
+
let(:value){ { constraint_name: :topics_pkey } }
|
173
|
+
should_not_update_updated_at_on_timestamp_columns
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "with :on_duplicate_key_update and validation checks turned off" do
|
178
|
+
asssertion_group(:should_support_on_duplicate_key_update) do
|
179
|
+
should_not_update_fields_not_mentioned
|
180
|
+
should_update_foreign_keys
|
181
|
+
should_not_update_created_at_on_timestamp_columns
|
182
|
+
should_update_updated_at_on_timestamp_columns
|
183
|
+
end
|
184
|
+
|
185
|
+
context "using a hash" do
|
186
|
+
context "with :columns a hash" do
|
187
|
+
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
188
|
+
let(:values){ [ [ 99, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
189
|
+
let(:updated_values){ [ [ 99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
190
|
+
|
191
|
+
macro(:perform_import) do |*opts|
|
192
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :conflict_target => :id, :columns => update_columns }, :validate => false)
|
193
|
+
end
|
194
|
+
|
195
|
+
setup do
|
196
|
+
Topic.import columns, values, :validate => false
|
197
|
+
@topic = Topic.find 99
|
198
|
+
end
|
199
|
+
|
200
|
+
context "using string hash map" do
|
201
|
+
let(:update_columns){ { "title" => "title", "author_email_address" => "author_email_address", "parent_id" => "parent_id" } }
|
202
|
+
should_support_on_duplicate_key_update
|
203
|
+
should_update_fields_mentioned
|
204
|
+
end
|
205
|
+
|
206
|
+
context "using string hash map, but specifying column mismatches" do
|
207
|
+
let(:update_columns){ { "title" => "author_email_address", "author_email_address" => "title", "parent_id" => "parent_id" } }
|
208
|
+
should_support_on_duplicate_key_update
|
209
|
+
should_update_fields_mentioned_with_hash_mappings
|
210
|
+
end
|
211
|
+
|
212
|
+
context "using symbol hash map" do
|
213
|
+
let(:update_columns){ { :title => :title, :author_email_address => :author_email_address, :parent_id => :parent_id } }
|
214
|
+
should_support_on_duplicate_key_update
|
215
|
+
should_update_fields_mentioned
|
216
|
+
end
|
217
|
+
|
218
|
+
context "using symbol hash map, but specifying column mismatches" do
|
219
|
+
let(:update_columns){ { :title => :author_email_address, :author_email_address => :title, :parent_id => :parent_id } }
|
220
|
+
should_support_on_duplicate_key_update
|
221
|
+
should_update_fields_mentioned_with_hash_mappings
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "with :constraint_name" do
|
226
|
+
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
227
|
+
let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
228
|
+
let(:updated_values){ [ [ 100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
229
|
+
|
230
|
+
macro(:perform_import) do |*opts|
|
231
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :constraint_name => :topics_pkey, :columns => update_columns }, :validate => false)
|
232
|
+
end
|
233
|
+
|
234
|
+
setup do
|
235
|
+
Topic.import columns, values, :validate => false
|
236
|
+
@topic = Topic.find 100
|
237
|
+
end
|
238
|
+
|
239
|
+
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
240
|
+
should_support_on_duplicate_key_update
|
241
|
+
should_update_fields_mentioned
|
242
|
+
end
|
243
|
+
|
244
|
+
context "with no :conflict_target or :constraint_name" do
|
245
|
+
let(:columns){ %w( id title author_name author_email_address parent_id ) }
|
246
|
+
let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com", 17 ] ] }
|
247
|
+
let(:updated_values){ [ [ 100, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57 ] ] }
|
248
|
+
|
249
|
+
macro(:perform_import) do |*opts|
|
250
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :columns => update_columns }, :validate => false)
|
251
|
+
end
|
252
|
+
|
253
|
+
setup do
|
254
|
+
Topic.import columns, values, :validate => false
|
255
|
+
@topic = Topic.find 100
|
256
|
+
end
|
257
|
+
|
258
|
+
context "default to the primary key" do
|
259
|
+
let(:update_columns){ [ :title, :author_email_address, :parent_id ] }
|
260
|
+
should_support_on_duplicate_key_update
|
261
|
+
should_update_fields_mentioned
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context "with no :columns" do
|
266
|
+
let(:columns){ %w( id title author_name author_email_address ) }
|
267
|
+
let(:values){ [ [ 100, "Book", "John Doe", "john@doe.com" ] ] }
|
268
|
+
let(:updated_values){ [ [ 100, "Title Should Not Change", "Author Should Not Change", "john@nogo.com" ] ] }
|
269
|
+
|
270
|
+
macro(:perform_import) do |*opts|
|
271
|
+
Topic.import columns, updated_values, opts.extract_options!.merge(:on_duplicate_key_update => { :conflict_target => :id }, :validate => false)
|
272
|
+
end
|
273
|
+
|
274
|
+
setup do
|
275
|
+
Topic.import columns, values, :validate => false
|
276
|
+
@topic = Topic.find 100
|
277
|
+
end
|
278
|
+
|
279
|
+
should_update_updated_at_on_timestamp_columns
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|