activerecord-import 0.2.9 → 0.2.10
Sign up to get free protection for your applications and to get access to all the features.
- 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 }
|