activerecord-import 0.2.9 → 0.2.10
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.
- data/README.markdown +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/activerecord-import/adapters/mysql_adapter.rb +6 -4
- data/lib/activerecord-import/import.rb +1 -1
- metadata +33 -61
- data/test/active_record/connection_adapter_test.rb +0 -52
- data/test/adapters/jdbcmysql.rb +0 -1
- data/test/adapters/mysql.rb +0 -1
- data/test/adapters/mysql2.rb +0 -1
- data/test/adapters/postgresql.rb +0 -1
- data/test/adapters/sqlite3.rb +0 -1
- data/test/import_test.rb +0 -242
- data/test/jdbcmysql/import_test.rb +0 -6
- data/test/models/book.rb +0 -3
- data/test/models/group.rb +0 -3
- data/test/models/topic.rb +0 -7
- data/test/mysql/import_test.rb +0 -6
- data/test/mysql2/import_test.rb +0 -6
- data/test/postgresql/import_test.rb +0 -20
- data/test/schema/generic_schema.rb +0 -98
- data/test/schema/mysql_schema.rb +0 -17
- data/test/schema/version.rb +0 -4
- data/test/support/active_support/test_case_extensions.rb +0 -67
- data/test/support/factories.rb +0 -13
- data/test/support/generate.rb +0 -29
- data/test/support/mysql/assertions.rb +0 -55
- data/test/support/mysql/import_examples.rb +0 -190
- data/test/synchronize_test.rb +0 -22
- data/test/test_helper.rb +0 -46
data/README.markdown
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
activerecord-import is a library for bulk inserting data using ActiveRecord.
|
4
4
|
|
5
|
-
For more information on activerecord-import please see its wiki:
|
5
|
+
For more information on activerecord-import please see its wiki: https://github.com/zdennis/activerecord-import/wiki
|
6
6
|
|
7
7
|
# License
|
8
8
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.10
|
@@ -5,10 +5,12 @@ module ActiveRecord::Import::MysqlAdapter
|
|
5
5
|
# Returns the maximum number of bytes that the server will allow
|
6
6
|
# in a single packet
|
7
7
|
def max_allowed_packet # :nodoc:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
@max_allowed_packet ||= begin
|
9
|
+
result = execute( "SHOW VARIABLES like 'max_allowed_packet';" )
|
10
|
+
# original Mysql gem responds to #fetch_row while Mysql2 responds to #first
|
11
|
+
val = result.respond_to?(:fetch_row) ? result.fetch_row[1] : result.first[1]
|
12
|
+
val.to_i
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
# Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
|
@@ -297,7 +297,7 @@ class ActiveRecord::Base
|
|
297
297
|
array_of_attributes.map do |arr|
|
298
298
|
my_values = arr.each_with_index.map do |val,j|
|
299
299
|
column = columns[j]
|
300
|
-
if !sequence_name.blank? && column.name == primary_key
|
300
|
+
if val.nil? && !sequence_name.blank? && column.name == primary_key
|
301
301
|
connection.next_value_for_sequence(sequence_name)
|
302
302
|
else
|
303
303
|
connection.quote(column.type_cast(val), column)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-import
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rake
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: jeweler
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 1.4.0
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: activerecord
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,7 +69,12 @@ dependencies:
|
|
54
69
|
version: '3.0'
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.0'
|
58
78
|
description: Extraction of the ActiveRecord::Base#import functionality from ar-extensions
|
59
79
|
for Rails 3 and beyond
|
60
80
|
email: zach.dennis@gmail.com
|
@@ -84,30 +104,6 @@ files:
|
|
84
104
|
- lib/activerecord-import/postgresql.rb
|
85
105
|
- lib/activerecord-import/sqlite3.rb
|
86
106
|
- lib/activerecord-import/synchronize.rb
|
87
|
-
- test/active_record/connection_adapter_test.rb
|
88
|
-
- test/adapters/jdbcmysql.rb
|
89
|
-
- test/adapters/mysql.rb
|
90
|
-
- test/adapters/mysql2.rb
|
91
|
-
- test/adapters/postgresql.rb
|
92
|
-
- test/adapters/sqlite3.rb
|
93
|
-
- test/import_test.rb
|
94
|
-
- test/jdbcmysql/import_test.rb
|
95
|
-
- test/models/book.rb
|
96
|
-
- test/models/group.rb
|
97
|
-
- test/models/topic.rb
|
98
|
-
- test/mysql/import_test.rb
|
99
|
-
- test/mysql2/import_test.rb
|
100
|
-
- test/postgresql/import_test.rb
|
101
|
-
- test/schema/generic_schema.rb
|
102
|
-
- test/schema/mysql_schema.rb
|
103
|
-
- test/schema/version.rb
|
104
|
-
- test/support/active_support/test_case_extensions.rb
|
105
|
-
- test/support/factories.rb
|
106
|
-
- test/support/generate.rb
|
107
|
-
- test/support/mysql/assertions.rb
|
108
|
-
- test/support/mysql/import_examples.rb
|
109
|
-
- test/synchronize_test.rb
|
110
|
-
- test/test_helper.rb
|
111
107
|
homepage: http://github.com/zdennis/activerecord-import
|
112
108
|
licenses: []
|
113
109
|
post_install_message:
|
@@ -122,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
118
|
version: '0'
|
123
119
|
segments:
|
124
120
|
- 0
|
125
|
-
hash: -
|
121
|
+
hash: -4211512731730455509
|
126
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
123
|
none: false
|
128
124
|
requirements:
|
@@ -131,32 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
127
|
version: '0'
|
132
128
|
requirements: []
|
133
129
|
rubyforge_project:
|
134
|
-
rubygems_version: 1.8.
|
130
|
+
rubygems_version: 1.8.24
|
135
131
|
signing_key:
|
136
132
|
specification_version: 3
|
137
133
|
summary: Bulk-loading extension for ActiveRecord
|
138
|
-
test_files:
|
139
|
-
- test/active_record/connection_adapter_test.rb
|
140
|
-
- test/adapters/jdbcmysql.rb
|
141
|
-
- test/adapters/mysql.rb
|
142
|
-
- test/adapters/mysql2.rb
|
143
|
-
- test/adapters/postgresql.rb
|
144
|
-
- test/adapters/sqlite3.rb
|
145
|
-
- test/import_test.rb
|
146
|
-
- test/jdbcmysql/import_test.rb
|
147
|
-
- test/models/book.rb
|
148
|
-
- test/models/group.rb
|
149
|
-
- test/models/topic.rb
|
150
|
-
- test/mysql/import_test.rb
|
151
|
-
- test/mysql2/import_test.rb
|
152
|
-
- test/postgresql/import_test.rb
|
153
|
-
- test/schema/generic_schema.rb
|
154
|
-
- test/schema/mysql_schema.rb
|
155
|
-
- test/schema/version.rb
|
156
|
-
- test/support/active_support/test_case_extensions.rb
|
157
|
-
- test/support/factories.rb
|
158
|
-
- test/support/generate.rb
|
159
|
-
- test/support/mysql/assertions.rb
|
160
|
-
- test/support/mysql/import_examples.rb
|
161
|
-
- test/synchronize_test.rb
|
162
|
-
- test/test_helper.rb
|
134
|
+
test_files: []
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
-
|
3
|
-
describe "ActiveRecord::ConnectionAdapter::AbstractAdapter" do
|
4
|
-
context "#get_insert_value_sets - computing insert value sets" do
|
5
|
-
let(:adapter){ ActiveRecord::ConnectionAdapters::AbstractAdapter }
|
6
|
-
let(:base_sql){ "INSERT INTO atable (a,b,c)" }
|
7
|
-
let(:values){ [ "(1,2,3)", "(2,3,4)", "(3,4,5)" ] }
|
8
|
-
|
9
|
-
context "when the max allowed bytes is 33 and the base SQL is 26 bytes" do
|
10
|
-
it "should return 3 value sets when given 3 value sets of 7 bytes a piece" do
|
11
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 33
|
12
|
-
assert_equal 3, value_sets.size
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when the max allowed bytes is 40 and the base SQL is 26 bytes" do
|
17
|
-
it "should return 3 value sets when given 3 value sets of 7 bytes a piece" do
|
18
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 40
|
19
|
-
assert_equal 3, value_sets.size
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context "when the max allowed bytes is 41 and the base SQL is 26 bytes" do
|
24
|
-
it "should return 2 value sets when given 2 value sets of 7 bytes a piece" do
|
25
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 41
|
26
|
-
assert_equal 2, value_sets.size
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context "when the max allowed bytes is 48 and the base SQL is 26 bytes" do
|
31
|
-
it "should return 2 value sets when given 2 value sets of 7 bytes a piece" do
|
32
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 48
|
33
|
-
assert_equal 2, value_sets.size
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when the max allowed bytes is 49 and the base SQL is 26 bytes" do
|
38
|
-
it "should return 1 value sets when given 1 value sets of 7 bytes a piece" do
|
39
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 49
|
40
|
-
assert_equal 1, value_sets.size
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "when the max allowed bytes is 999999 and the base SQL is 26 bytes" do
|
45
|
-
it "should return 1 value sets when given 1 value sets of 7 bytes a piece" do
|
46
|
-
value_sets = adapter.get_insert_value_sets values, base_sql.size, max_allowed_bytes = 999999
|
47
|
-
assert_equal 1, value_sets.size
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
data/test/adapters/jdbcmysql.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ENV["ARE_DB"] = "jdbcmysql"
|
data/test/adapters/mysql.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ENV["ARE_DB"] = "mysql"
|
data/test/adapters/mysql2.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ENV["ARE_DB"] = "mysql2"
|
data/test/adapters/postgresql.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ENV["ARE_DB"] = "postgresql"
|
data/test/adapters/sqlite3.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ENV["ARE_DB"] = "sqlite3"
|
data/test/import_test.rb
DELETED
@@ -1,242 +0,0 @@
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
2
|
-
|
3
|
-
describe "#import" do
|
4
|
-
it "should return the number of inserts performed" do
|
5
|
-
# see ActiveRecord::ConnectionAdapters::AbstractAdapter test for more specifics
|
6
|
-
assert_difference "Topic.count", +10 do
|
7
|
-
result = Topic.import Build(3, :topics)
|
8
|
-
assert result.num_inserts > 0
|
9
|
-
|
10
|
-
result = Topic.import Build(7, :topics)
|
11
|
-
assert result.num_inserts > 0
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should not produce an error when importing empty arrays" do
|
16
|
-
assert_nothing_raised do
|
17
|
-
Topic.import []
|
18
|
-
Topic.import %w(title author_name), []
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "with :validation option" do
|
23
|
-
let(:columns) { %w(title author_name) }
|
24
|
-
let(:valid_values) { [[ "LDAP", "Jerry Carter"], ["Rails Recipes", "Chad Fowler"]] }
|
25
|
-
let(:invalid_values) { [[ "The RSpec Book", ""], ["Agile+UX", ""]] }
|
26
|
-
|
27
|
-
context "with validation checks turned off" do
|
28
|
-
it "should import valid data" do
|
29
|
-
assert_difference "Topic.count", +2 do
|
30
|
-
result = Topic.import columns, valid_values, :validate => false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should import invalid data" do
|
35
|
-
assert_difference "Topic.count", +2 do
|
36
|
-
result = Topic.import columns, invalid_values, :validate => false
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context "with validation checks turned on" do
|
42
|
-
it "should import valid data" do
|
43
|
-
assert_difference "Topic.count", +2 do
|
44
|
-
result = Topic.import columns, valid_values, :validate => true
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should not import invalid data" do
|
49
|
-
assert_no_difference "Topic.count" do
|
50
|
-
result = Topic.import columns, invalid_values, :validate => true
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should report the failed instances" do
|
55
|
-
results = Topic.import columns, invalid_values, :validate => true
|
56
|
-
assert_equal invalid_values.size, results.failed_instances.size
|
57
|
-
results.failed_instances.each{ |e| assert_kind_of Topic, e }
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should import valid data when mixed with invalid data" do
|
61
|
-
assert_difference "Topic.count", +2 do
|
62
|
-
result = Topic.import columns, valid_values + invalid_values, :validate => true
|
63
|
-
end
|
64
|
-
assert_equal 0, Topic.find_all_by_title(invalid_values.map(&:first)).count
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
context "with :synchronize option" do
|
70
|
-
context "synchronizing on new records" do
|
71
|
-
let(:new_topics) { Build(3, :topics) }
|
72
|
-
|
73
|
-
it "doesn't reload any data (doesn't work)" do
|
74
|
-
Topic.import new_topics, :synchronize => new_topics
|
75
|
-
assert new_topics.all?(&:new_record?), "No record should have been reloaded"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
context "synchronizing on new records with explicit conditions" do
|
80
|
-
let(:new_topics) { Build(3, :topics) }
|
81
|
-
|
82
|
-
it "reloads data for existing in-memory instances" do
|
83
|
-
Topic.import(new_topics, :synchronize => new_topics, :synchronize_key => [:title] )
|
84
|
-
assert new_topics.all?(&:new_record?), "Records should have been reloaded"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "with an array of unsaved model instances" do
|
90
|
-
let(:topic) { Build(:topic, :title => "The RSpec Book", :author_name => "David Chelimsky")}
|
91
|
-
let(:topics) { Build(9, :topics) }
|
92
|
-
let(:invalid_topics){ Build(7, :invalid_topics)}
|
93
|
-
|
94
|
-
it "should import records based on those model's attributes" do
|
95
|
-
assert_difference "Topic.count", +9 do
|
96
|
-
result = Topic.import topics
|
97
|
-
end
|
98
|
-
|
99
|
-
Topic.import [topic]
|
100
|
-
assert Topic.find_by_title_and_author_name("The RSpec Book", "David Chelimsky")
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should not overwrite existing records" do
|
104
|
-
topic = Generate(:topic, :title => "foobar")
|
105
|
-
assert_no_difference "Topic.count" do
|
106
|
-
begin
|
107
|
-
Topic.transaction do
|
108
|
-
topic.title = "baz"
|
109
|
-
Topic.import [topic]
|
110
|
-
end
|
111
|
-
rescue Exception
|
112
|
-
# PostgreSQL raises PgError due to key constraints
|
113
|
-
# I don't know why ActiveRecord doesn't catch these. *sigh*
|
114
|
-
end
|
115
|
-
end
|
116
|
-
assert_equal "foobar", topic.reload.title
|
117
|
-
end
|
118
|
-
|
119
|
-
context "with validation checks turned on" do
|
120
|
-
it "should import valid models" do
|
121
|
-
assert_difference "Topic.count", +9 do
|
122
|
-
result = Topic.import topics, :validate => true
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should not import invalid models" do
|
127
|
-
assert_no_difference "Topic.count" do
|
128
|
-
result = Topic.import invalid_topics, :validate => true
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
context "with validation checks turned off" do
|
134
|
-
it "should import invalid models" do
|
135
|
-
assert_difference "Topic.count", +7 do
|
136
|
-
result = Topic.import invalid_topics, :validate => false
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "with an array of columns and an array of unsaved model instances" do
|
143
|
-
let(:topics) { Build(2, :topics) }
|
144
|
-
|
145
|
-
it "should import records populating the supplied columns with the corresponding model instance attributes" do
|
146
|
-
assert_difference "Topic.count", +2 do
|
147
|
-
result = Topic.import [:author_name, :title], topics
|
148
|
-
end
|
149
|
-
|
150
|
-
# imported topics should be findable by their imported attributes
|
151
|
-
assert Topic.find_by_author_name(topics.first.author_name)
|
152
|
-
assert Topic.find_by_author_name(topics.last.author_name)
|
153
|
-
end
|
154
|
-
|
155
|
-
it "should not populate fields for columns not imported" do
|
156
|
-
topics.first.author_email_address = "zach.dennis@gmail.com"
|
157
|
-
assert_difference "Topic.count", +2 do
|
158
|
-
result = Topic.import [:author_name, :title], topics
|
159
|
-
end
|
160
|
-
|
161
|
-
assert !Topic.find_by_author_email_address("zach.dennis@gmail.com")
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
context "with an array of columns and an array of values" do
|
166
|
-
it "should import ids when specified" do
|
167
|
-
Topic.import [:id, :author_name, :title], [[99, "Bob Jones", "Topic 99"]]
|
168
|
-
assert_equal 99, Topic.last.id
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
context "ActiveRecord timestamps" do
|
173
|
-
context "when the timestamps columns are present" do
|
174
|
-
setup do
|
175
|
-
Delorean.time_travel_to("5 minutes ago") do
|
176
|
-
assert_difference "Book.count", +1 do
|
177
|
-
result = Book.import [:title, :author_name, :publisher], [["LDAP", "Big Bird", "Del Rey"]]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
@book = Book.last
|
181
|
-
end
|
182
|
-
|
183
|
-
it "should set the created_at column for new records" do
|
184
|
-
assert_equal 5.minutes.ago.strftime("%H:%M"), @book.created_at.strftime("%H:%M")
|
185
|
-
end
|
186
|
-
|
187
|
-
it "should set the created_on column for new records" do
|
188
|
-
assert_equal 5.minutes.ago.strftime("%H:%M"), @book.created_on.strftime("%H:%M")
|
189
|
-
end
|
190
|
-
|
191
|
-
it "should set the updated_at column for new records" do
|
192
|
-
assert_equal 5.minutes.ago.strftime("%H:%M"), @book.updated_at.strftime("%H:%M")
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should set the updated_on column for new records" do
|
196
|
-
assert_equal 5.minutes.ago.strftime("%H:%M"), @book.updated_on.strftime("%H:%M")
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
context "when a custom time zone is set" do
|
201
|
-
setup do
|
202
|
-
original_timezone = ActiveRecord::Base.default_timezone
|
203
|
-
ActiveRecord::Base.default_timezone = :utc
|
204
|
-
Delorean.time_travel_to("5 minutes ago") do
|
205
|
-
assert_difference "Book.count", +1 do
|
206
|
-
result = Book.import [:title, :author_name, :publisher], [["LDAP", "Big Bird", "Del Rey"]]
|
207
|
-
end
|
208
|
-
end
|
209
|
-
ActiveRecord::Base.default_timezone = original_timezone
|
210
|
-
@book = Book.last
|
211
|
-
end
|
212
|
-
|
213
|
-
it "should set the created_at and created_on timestamps for new records" do
|
214
|
-
assert_equal 5.minutes.ago.utc.strftime("%H:%M"), @book.created_at.strftime("%H:%M")
|
215
|
-
assert_equal 5.minutes.ago.utc.strftime("%H:%M"), @book.created_on.strftime("%H:%M")
|
216
|
-
end
|
217
|
-
|
218
|
-
it "should set the updated_at and updated_on timestamps for new records" do
|
219
|
-
assert_equal 5.minutes.ago.utc.strftime("%H:%M"), @book.updated_at.strftime("%H:%M")
|
220
|
-
assert_equal 5.minutes.ago.utc.strftime("%H:%M"), @book.updated_on.strftime("%H:%M")
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
context "importing with database reserved words" do
|
226
|
-
let(:group) { Build(:group, :order => "superx") }
|
227
|
-
|
228
|
-
it "should import just fine" do
|
229
|
-
assert_difference "Group.count", +1 do
|
230
|
-
result = Group.import [group]
|
231
|
-
end
|
232
|
-
assert_equal "superx", Group.first.order
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
context "importing a datetime field" do
|
237
|
-
it "should import a date with YYYY/MM/DD format just fine" do
|
238
|
-
Topic.import [:author_name, :title, :last_read], [["Bob Jones", "Topic 2", "2010/05/14"]]
|
239
|
-
assert_equal "2010/05/14".to_date, Topic.last.last_read.to_date
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
@@ -1,6 +0,0 @@
|
|
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
DELETED
data/test/models/group.rb
DELETED
data/test/models/topic.rb
DELETED
@@ -1,7 +0,0 @@
|
|
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
|
data/test/mysql/import_test.rb
DELETED
@@ -1,6 +0,0 @@
|
|
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/mysql2/import_test.rb
DELETED
@@ -1,6 +0,0 @@
|
|
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
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require File.expand_path('../../test_helper', __FILE__)
|
2
|
-
|
3
|
-
describe "#supports_imports?" do
|
4
|
-
it "should support import" do
|
5
|
-
assert ActiveRecord::Base.supports_import?
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#import" do
|
10
|
-
it "should import with a single insert" do
|
11
|
-
# see ActiveRecord::ConnectionAdapters::AbstractAdapter test for more specifics
|
12
|
-
assert_difference "Topic.count", +10 do
|
13
|
-
result = Topic.import Build(3, :topics)
|
14
|
-
assert_equal 1, result.num_inserts
|
15
|
-
|
16
|
-
result = Topic.import Build(7, :topics)
|
17
|
-
assert_equal 1, result.num_inserts
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,98 +0,0 @@
|
|
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
|
-
end
|
data/test/schema/mysql_schema.rb
DELETED
@@ -1,17 +0,0 @@
|
|
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
|
data/test/schema/version.rb
DELETED
@@ -1,67 +0,0 @@
|
|
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
|
-
|
data/test/support/factories.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
Factory.define :group do |m|
|
2
|
-
m.sequence(:order) { |n| "Order #{n}" }
|
3
|
-
end
|
4
|
-
|
5
|
-
Factory.define :invalid_topic, :class => "Topic" do |m|
|
6
|
-
m.sequence(:title){ |n| "Title #{n}"}
|
7
|
-
m.author_name nil
|
8
|
-
end
|
9
|
-
|
10
|
-
Factory.define :topic do |m|
|
11
|
-
m.sequence(:title){ |n| "Title #{n}"}
|
12
|
-
m.sequence(:author_name){ |n| "Author #{n}"}
|
13
|
-
end
|
data/test/support/generate.rb
DELETED
@@ -1,29 +0,0 @@
|
|
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 << Factory.build(factory.to_s.singularize.to_sym, factory_girl_args) }
|
10
|
-
end
|
11
|
-
else
|
12
|
-
Factory.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 << Factory.create(factory.to_s.singularize.to_sym, factory_girl_args) }
|
24
|
-
end
|
25
|
-
else
|
26
|
-
Factory.create(factory.to_s.singularize.to_sym, factory_girl_args)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,55 +0,0 @@
|
|
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
|
@@ -1,190 +0,0 @@
|
|
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
|
data/test/synchronize_test.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
2
|
-
|
3
|
-
describe ".synchronize" do
|
4
|
-
let(:topics){ Generate(3, :topics) }
|
5
|
-
let(:titles){ %w(one two three) }
|
6
|
-
|
7
|
-
setup do
|
8
|
-
# update records outside of ActiveRecord knowing about it
|
9
|
-
Topic.connection.execute( "UPDATE #{Topic.table_name} SET title='#{titles[0]}_haha' WHERE id=#{topics[0].id}", "Updating record 1 without ActiveRecord" )
|
10
|
-
Topic.connection.execute( "UPDATE #{Topic.table_name} SET title='#{titles[1]}_haha' WHERE id=#{topics[1].id}", "Updating record 2 without ActiveRecord" )
|
11
|
-
Topic.connection.execute( "UPDATE #{Topic.table_name} SET title='#{titles[2]}_haha' WHERE id=#{topics[2].id}", "Updating record 3 without ActiveRecord" )
|
12
|
-
end
|
13
|
-
|
14
|
-
it "reloads data for the specified records" do
|
15
|
-
Book.synchronize topics
|
16
|
-
|
17
|
-
actual_titles = topics.map(&:title)
|
18
|
-
assert_equal "#{titles[0]}_haha", actual_titles[0], "the first record was not correctly updated"
|
19
|
-
assert_equal "#{titles[1]}_haha", actual_titles[1], "the second record was not correctly updated"
|
20
|
-
assert_equal "#{titles[2]}_haha", actual_titles[2], "the third record was not correctly updated"
|
21
|
-
end
|
22
|
-
end
|
data/test/test_helper.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
test_dir = Pathname.new File.dirname(__FILE__)
|
3
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
-
|
6
|
-
require "fileutils"
|
7
|
-
require "rubygems"
|
8
|
-
|
9
|
-
ENV["RAILS_ENV"] = "test"
|
10
|
-
|
11
|
-
require "bundler"
|
12
|
-
Bundler.setup
|
13
|
-
|
14
|
-
require "logger"
|
15
|
-
require 'test/unit'
|
16
|
-
require "active_record"
|
17
|
-
require "active_record/fixtures"
|
18
|
-
require "active_support/test_case"
|
19
|
-
|
20
|
-
require "delorean"
|
21
|
-
require "ruby-debug"
|
22
|
-
|
23
|
-
adapter = ENV["ARE_DB"] || "sqlite3"
|
24
|
-
|
25
|
-
FileUtils.mkdir_p 'log'
|
26
|
-
ActiveRecord::Base.logger = Logger.new("log/test.log")
|
27
|
-
ActiveRecord::Base.logger.level = Logger::DEBUG
|
28
|
-
ActiveRecord::Base.configurations["test"] = YAML.load(test_dir.join("database.yml").open)[adapter]
|
29
|
-
|
30
|
-
require "activerecord-import"
|
31
|
-
ActiveRecord::Base.establish_connection "test"
|
32
|
-
|
33
|
-
ActiveSupport::Notifications.subscribe(/active_record.sql/) do |event, _, _, _, hsh|
|
34
|
-
ActiveRecord::Base.logger.info hsh[:sql]
|
35
|
-
end
|
36
|
-
|
37
|
-
require "factory_girl"
|
38
|
-
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each{ |file| require file }
|
39
|
-
|
40
|
-
# Load base/generic schema
|
41
|
-
require test_dir.join("schema/version")
|
42
|
-
require test_dir.join("schema/generic_schema")
|
43
|
-
adapter_schema = test_dir.join("schema/#{adapter}_schema.rb")
|
44
|
-
require adapter_schema if File.exists?(adapter_schema)
|
45
|
-
|
46
|
-
Dir[File.dirname(__FILE__) + "/models/*.rb"].each{ |file| require file }
|