jorahood-ar-extensions 0.9.2.3
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/ChangeLog +145 -0
- data/README +167 -0
- data/Rakefile +79 -0
- data/config/database.yml +7 -0
- data/config/database.yml.template +7 -0
- data/config/mysql.schema +72 -0
- data/config/postgresql.schema +39 -0
- data/db/migrate/generic_schema.rb +96 -0
- data/db/migrate/mysql_schema.rb +31 -0
- data/db/migrate/oracle_schema.rb +5 -0
- data/db/migrate/version.rb +4 -0
- data/init.rb +31 -0
- data/lib/ar-extensions/create_and_update.rb +509 -0
- data/lib/ar-extensions/csv.rb +309 -0
- data/lib/ar-extensions/delete.rb +143 -0
- data/lib/ar-extensions/extensions.rb +506 -0
- data/lib/ar-extensions/finder_options.rb +275 -0
- data/lib/ar-extensions/finders.rb +94 -0
- data/lib/ar-extensions/foreign_keys.rb +70 -0
- data/lib/ar-extensions/fulltext.rb +62 -0
- data/lib/ar-extensions/import.rb +352 -0
- data/lib/ar-extensions/insert_select.rb +178 -0
- data/lib/ar-extensions/synchronize.rb +30 -0
- data/lib/ar-extensions/temporary_table.rb +124 -0
- data/lib/ar-extensions/union.rb +204 -0
- data/lib/ar-extensions/version.rb +9 -0
- data/tests/connections/native_mysql/connection.rb +16 -0
- data/tests/connections/native_oracle/connection.rb +16 -0
- data/tests/connections/native_postgresql/connection.rb +19 -0
- data/tests/connections/native_sqlite/connection.rb +14 -0
- data/tests/connections/native_sqlite3/connection.rb +14 -0
- data/tests/fixtures/addresses.yml +25 -0
- data/tests/fixtures/books.yml +46 -0
- data/tests/fixtures/developers.yml +20 -0
- data/tests/fixtures/unit/active_record_base_finders/addresses.yml +25 -0
- data/tests/fixtures/unit/active_record_base_finders/books.yml +64 -0
- data/tests/fixtures/unit/active_record_base_finders/developers.yml +20 -0
- data/tests/fixtures/unit/synchronize/books.yml +16 -0
- data/tests/fixtures/unit/to_csv_headers/addresses.yml +8 -0
- data/tests/fixtures/unit/to_csv_headers/developers.yml +6 -0
- data/tests/fixtures/unit/to_csv_with_common_options/addresses.yml +40 -0
- data/tests/fixtures/unit/to_csv_with_common_options/developers.yml +13 -0
- data/tests/fixtures/unit/to_csv_with_common_options/languages.yml +29 -0
- data/tests/fixtures/unit/to_csv_with_common_options/teams.yml +3 -0
- data/tests/fixtures/unit/to_csv_with_default_options/developers.yml +7 -0
- data/tests/models/address.rb +4 -0
- data/tests/models/animal.rb +2 -0
- data/tests/models/book.rb +3 -0
- data/tests/models/cart_item.rb +4 -0
- data/tests/models/developer.rb +8 -0
- data/tests/models/group.rb +3 -0
- data/tests/models/language.rb +5 -0
- data/tests/models/mysql/book.rb +3 -0
- data/tests/models/mysql/test_innodb.rb +3 -0
- data/tests/models/mysql/test_memory.rb +3 -0
- data/tests/models/mysql/test_myisam.rb +3 -0
- data/tests/models/project.rb +2 -0
- data/tests/models/shopping_cart.rb +4 -0
- data/tests/models/team.rb +4 -0
- data/tests/models/topic.rb +13 -0
- data/tests/mysql/test_create_and_update.rb +290 -0
- data/tests/mysql/test_delete.rb +142 -0
- data/tests/mysql/test_finder_options.rb +121 -0
- data/tests/mysql/test_finders.rb +29 -0
- data/tests/mysql/test_import.rb +354 -0
- data/tests/mysql/test_insert_select.rb +173 -0
- data/tests/mysql/test_mysql_adapter.rb +45 -0
- data/tests/mysql/test_union.rb +81 -0
- data/tests/oracle/test_adapter.rb +14 -0
- data/tests/postgresql/test_adapter.rb +14 -0
- metadata +147 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require File.expand_path( File.join( File.dirname( __FILE__ ), '..', 'test_helper' ) )
|
|
2
|
+
|
|
3
|
+
class MysqlFindersTest< TestCaseSuperClass
|
|
4
|
+
include ActiveRecord::ConnectionAdapters
|
|
5
|
+
self.fixture_path = File.join( File.dirname( __FILE__ ), '../fixtures/unit/active_record_base_finders' )
|
|
6
|
+
self.fixtures :books
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@connection = ActiveRecord::Base.connection
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def teardown
|
|
13
|
+
Book.delete_all
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# FIXME this won't work until full text index/searching is added for
|
|
17
|
+
# any db adapter outside of MySQL.
|
|
18
|
+
# For PostgreSQL support look into TSearch2 support which is
|
|
19
|
+
# builtin to PostgreSQL 8.x (but not in 7.x)
|
|
20
|
+
def test_find_three_results_using_match
|
|
21
|
+
unless Book.supports_full_text_searching?
|
|
22
|
+
STDERR.puts "test_find_three_results_using_match is not testing, since your database adapter doesn't support fulltext searching"
|
|
23
|
+
else
|
|
24
|
+
books = Book.find( :all, :conditions=>{ :match_title=> 'Terry' } )
|
|
25
|
+
assert_equal( 4, books.size )
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
require File.expand_path( File.join( File.dirname( __FILE__ ), '..', 'test_helper') )
|
|
2
|
+
|
|
3
|
+
class MysqlImportTest< TestCaseSuperClass
|
|
4
|
+
fixtures :topics, :books
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
@connection = ActiveRecord::Base.connection
|
|
8
|
+
@columns_for_on_duplicate_key_update = [ 'id', 'title', 'author_name']
|
|
9
|
+
Topic.delete_all
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def teardown
|
|
13
|
+
Topic.delete_all
|
|
14
|
+
Book.delete_all
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# sets up base data for on duplicate key update tests
|
|
18
|
+
def setup_import_without_validations_but_with_on_duplicate_key_update
|
|
19
|
+
columns = @columns_for_on_duplicate_key_update
|
|
20
|
+
values = [ [ 1, 'Book', 'Author' ] ]
|
|
21
|
+
Topic.import( columns, values, :validate=>false )
|
|
22
|
+
Topic.find_by_id( 1 )
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_that_synchronizes_existing_AR_instances
|
|
26
|
+
topics = []
|
|
27
|
+
topics << Topic.create!( :title=>"LDAP", :author_name=>"Big Bird" )
|
|
28
|
+
topics << Topic.create!( :title=>"Rails Recipes", :author_name=>"Elmo")
|
|
29
|
+
|
|
30
|
+
columns = %W{ id author_name }
|
|
31
|
+
values = []
|
|
32
|
+
values << [ topics.first.id, "Jerry Carter" ]
|
|
33
|
+
values << [ topics.last.id, "Chad Fowler" ]
|
|
34
|
+
|
|
35
|
+
columns2update = [ 'author_name' ]
|
|
36
|
+
|
|
37
|
+
expected_count = Topic.count
|
|
38
|
+
Topic.import( columns, values,
|
|
39
|
+
:validate=>false,
|
|
40
|
+
:on_duplicate_key_update=>columns2update,
|
|
41
|
+
:synchronize=>topics )
|
|
42
|
+
|
|
43
|
+
assert_equal expected_count, Topic.count, "no new records should have been created!"
|
|
44
|
+
assert_equal "Jerry Carter", topics.first.author_name, "wrong author!"
|
|
45
|
+
assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_string_array1
|
|
49
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
50
|
+
|
|
51
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
52
|
+
columns = @columns_for_on_duplicate_key_update
|
|
53
|
+
|
|
54
|
+
# The author_name is NOT supposed to change.
|
|
55
|
+
columns2update = [ 'title' ]
|
|
56
|
+
updated_values = [ [ 1, 'Book - 2nd Edition', 'New Author' ] ]
|
|
57
|
+
Topic.import( columns, updated_values,
|
|
58
|
+
:validate=>false,
|
|
59
|
+
:on_duplicate_key_update=>columns2update )
|
|
60
|
+
topic = Topic.find_by_id( 1 )
|
|
61
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
62
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_string_array2
|
|
66
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
67
|
+
|
|
68
|
+
setup_import_without_validations_but_with_on_duplicate_key_update
|
|
69
|
+
columns = @columns_for_on_duplicate_key_update
|
|
70
|
+
|
|
71
|
+
# note that both the title and the author name should change here
|
|
72
|
+
columns2update = [ 'title', 'author_name' ]
|
|
73
|
+
updated_values = [ [ 1, 'Book - 2nd Edition', 'New Author' ] ]
|
|
74
|
+
Topic.import( columns, updated_values,
|
|
75
|
+
:validate=>false,
|
|
76
|
+
:on_duplicate_key_update=>columns2update )
|
|
77
|
+
topic = Topic.find_by_id( 1 )
|
|
78
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
79
|
+
assert_equal updated_values[0][2], topic.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_symbol_array1
|
|
83
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
84
|
+
|
|
85
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
86
|
+
columns = @columns_for_on_duplicate_key_update
|
|
87
|
+
|
|
88
|
+
# test updates with array with symbol(s) *note that author_name isn't supposed to change
|
|
89
|
+
columns2update = [ :title ]
|
|
90
|
+
updated_values = [ [ 1, 'Book - 3rd Edition', 'New Author' ] ]
|
|
91
|
+
Topic.import( columns, updated_values,
|
|
92
|
+
:validate=>false,
|
|
93
|
+
:on_duplicate_key_update=>columns2update )
|
|
94
|
+
topic = Topic.find_by_id( 1 )
|
|
95
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
96
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_symbol_array2
|
|
100
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
101
|
+
|
|
102
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
103
|
+
columns = @columns_for_on_duplicate_key_update
|
|
104
|
+
|
|
105
|
+
# Note that the title and author's name are supposed to change unlik the previous assertion
|
|
106
|
+
columns2update = [ :title, :author_name ]
|
|
107
|
+
updated_values = [ [ 1, 'Book - 4th Edition', 'New Author' ] ]
|
|
108
|
+
Topic.import( columns, updated_values,
|
|
109
|
+
:validate=>false,
|
|
110
|
+
:on_duplicate_key_update=>columns2update )
|
|
111
|
+
topic = Topic.find_by_id( 1 )
|
|
112
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
113
|
+
assert_equal updated_values[0][2], topic.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_string_hash1
|
|
117
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
118
|
+
|
|
119
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
120
|
+
columns = @columns_for_on_duplicate_key_update
|
|
121
|
+
|
|
122
|
+
# Note that the title is supposed to change but NOT the author's name
|
|
123
|
+
columns2update = { 'title'=>'title' }
|
|
124
|
+
updated_values = [ [ 1, 'Book - 5th Edition', 'New Author' ] ]
|
|
125
|
+
Topic.import( columns, updated_values,
|
|
126
|
+
:validate=>false,
|
|
127
|
+
:on_duplicate_key_update=>columns2update )
|
|
128
|
+
topic = Topic.find_by_id( 1 )
|
|
129
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
130
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_string_hash2
|
|
134
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
135
|
+
|
|
136
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
137
|
+
columns = @columns_for_on_duplicate_key_update
|
|
138
|
+
|
|
139
|
+
# Note that the title is supposed to change to the author's name, but the
|
|
140
|
+
# author's name is NOT supposed to change
|
|
141
|
+
columns2update = { 'title'=>'author_name' }
|
|
142
|
+
updated_values = [ [ 1, 'Book - 6th Edition', 'New Author' ] ]
|
|
143
|
+
Topic.import( columns, updated_values,
|
|
144
|
+
:validate=>false,
|
|
145
|
+
:on_duplicate_key_update=>columns2update )
|
|
146
|
+
topic = Topic.find_by_id( 1 )
|
|
147
|
+
assert_equal updated_values[0][2], topic.title, "The book title is wrong! It was supposed to change to the author's name!"
|
|
148
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_string_hash3
|
|
152
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
153
|
+
|
|
154
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
155
|
+
columns = @columns_for_on_duplicate_key_update
|
|
156
|
+
|
|
157
|
+
# Note that the title AND the author_name is supposed to change
|
|
158
|
+
columns2update = { 'title'=>'title', 'author_name'=>'author_name' }
|
|
159
|
+
updated_values = [ [ 1, 'Book - 7th Edition', 'New Author' ] ]
|
|
160
|
+
Topic.import( columns, updated_values,
|
|
161
|
+
:validate=>false,
|
|
162
|
+
:on_duplicate_key_update=>columns2update )
|
|
163
|
+
topic = Topic.find_by_id( 1 )
|
|
164
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
165
|
+
assert_equal updated_values[0][2], topic.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_symbol_hash1
|
|
169
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
170
|
+
|
|
171
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
172
|
+
columns = @columns_for_on_duplicate_key_update
|
|
173
|
+
|
|
174
|
+
# Note that the title is supposed to change but NOT the author's name
|
|
175
|
+
columns2update = { :title=>:title }
|
|
176
|
+
updated_values = [ [ 1, 'Book - 8th Edition', 'New Author' ] ]
|
|
177
|
+
Topic.import( columns, updated_values,
|
|
178
|
+
:validate=>false,
|
|
179
|
+
:on_duplicate_key_update=>columns2update )
|
|
180
|
+
topic = Topic.find_by_id( 1 )
|
|
181
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
182
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_symbol_hash2
|
|
186
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
187
|
+
|
|
188
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
189
|
+
columns = @columns_for_on_duplicate_key_update
|
|
190
|
+
|
|
191
|
+
# Note that the title is supposed to change to the author's name, but the
|
|
192
|
+
# author's name is NOT supposed to change
|
|
193
|
+
columns2update = { :title=>:author_name }
|
|
194
|
+
updated_values = [ [ 1, 'Book - 9th Edition', 'New Author' ] ]
|
|
195
|
+
Topic.import( columns, updated_values,
|
|
196
|
+
:validate=>false,
|
|
197
|
+
:on_duplicate_key_update=>columns2update )
|
|
198
|
+
topic = Topic.find_by_id( 1 )
|
|
199
|
+
assert_equal updated_values[0][2], topic.title, "The book title is wrong! It was supposed to change to the author's name!"
|
|
200
|
+
assert_equal orig_topic.author_name, topic.author_name, "The author's name is incorrect! It wasn't supposed to change!"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_symbol_hash3
|
|
204
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
205
|
+
orig_topic = setup_import_without_validations_but_with_on_duplicate_key_update
|
|
206
|
+
columns = @columns_for_on_duplicate_key_update
|
|
207
|
+
|
|
208
|
+
# Note that the title AND the author_name is supposed to change
|
|
209
|
+
columns2update = { :title=>:title, :author_name=>:author_name }
|
|
210
|
+
updated_values = [ [ 1, 'Book - 10th Edition', 'New Author' ] ]
|
|
211
|
+
|
|
212
|
+
Topic.import( columns, updated_values,
|
|
213
|
+
:validate=>false,
|
|
214
|
+
:on_duplicate_key_update=>columns2update )
|
|
215
|
+
|
|
216
|
+
topic = Topic.find_by_id( 1 )
|
|
217
|
+
assert_equal updated_values[0][1], topic.title, "The book title is wrong! It was supposed to change!"
|
|
218
|
+
assert_equal updated_values[0][2], topic.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_import_with_array_of_model_objects_with_on_duplicate_key_update
|
|
222
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
223
|
+
|
|
224
|
+
topic = Topic.create( :title=>"Book", :author_name=>"Someguy" )
|
|
225
|
+
topic2 = Topic.create( :title=>"Book2", :author_name=>"Someguy" )
|
|
226
|
+
|
|
227
|
+
topic.author_name = "SomeNewguy"
|
|
228
|
+
topic2.author_name = "SomeOtherNewguy"
|
|
229
|
+
|
|
230
|
+
Topic.import( [ topic, topic2 ], :on_duplicate_key_update=>[ :author_name ] )
|
|
231
|
+
topic.reload
|
|
232
|
+
topic2.reload
|
|
233
|
+
|
|
234
|
+
assert_equal "SomeNewguy", topic.author_name
|
|
235
|
+
assert_equal "SomeOtherNewguy", topic2.author_name
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def test_import_without_validations_but_with_on_duplicate_key_update_using_associated_objects
|
|
239
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
240
|
+
|
|
241
|
+
topic1 = Topic.create( :title=>"Topic1", :author_name=>"Someguy" )
|
|
242
|
+
topic2 = Topic.create( :title=>"Topic2", :author_name=>"Someguy" )
|
|
243
|
+
|
|
244
|
+
book1 = Book.create :title=>"book1", :author_name=>"Zach", :publisher=>"Pub", :topic_id=>topic1.id
|
|
245
|
+
book2 = Book.create :title=>"book2", :author_name=>"Mark", :publisher=>"Pub", :topic_id=>topic1.id
|
|
246
|
+
|
|
247
|
+
book1.topic = topic2
|
|
248
|
+
book2.topic = topic1
|
|
249
|
+
|
|
250
|
+
# Note that the title is supposed to change
|
|
251
|
+
columns = [ :id, :title, :author_name, :topic_id ]
|
|
252
|
+
columns2update = [ :title, :author_name, :topic_id ]
|
|
253
|
+
updated_values = [
|
|
254
|
+
[ book1.id, 'Book - 1st Edition', 'New Author', book1.topic.id ],
|
|
255
|
+
[ book2.id, 'Book - 2nd Edition', 'New Author', book2.topic.id ] ]
|
|
256
|
+
Book.import( columns, updated_values,
|
|
257
|
+
:validate=>false,
|
|
258
|
+
:on_duplicate_key_update=>columns2update )
|
|
259
|
+
|
|
260
|
+
book1.reload
|
|
261
|
+
book2.reload
|
|
262
|
+
|
|
263
|
+
assert_equal updated_values[0][1], book1.title, "The book title is wrong! It was supposed to change!"
|
|
264
|
+
assert_equal updated_values[0][2], book1.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
265
|
+
assert_equal updated_values[0][3], book1.topic_id, "The topic id is wrong!"
|
|
266
|
+
|
|
267
|
+
assert_equal updated_values[1][1], book2.title, "The book title is wrong! It was supposed to change!"
|
|
268
|
+
assert_equal updated_values[1][2], book2.author_name, "The author's name is incorrect! It was supposed to change!"
|
|
269
|
+
assert_equal updated_values[1][3], book2.topic_id, "The topic id is wrong!"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def test_import_with_on_duplicate_key_update_with_associated_objects_saves_foreign_keys
|
|
273
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
274
|
+
|
|
275
|
+
topic1 = Topic.create( :title=>"Topic1", :author_name=>"Someguy" )
|
|
276
|
+
topic2 = Topic.create( :title=>"Topic2", :author_name=>"Someguy" )
|
|
277
|
+
|
|
278
|
+
book1 = Book.create :title=>"book1", :author_name=>"Zach", :publisher=>"Pub", :topic_id=>topic1.id
|
|
279
|
+
book2 = Book.create :title=>"book2", :author_name=>"Mark", :publisher=>"Pub", :topic_id=>topic1.id
|
|
280
|
+
book3 = Book.create :title=>"book3", :author_name=>"Zach", :publisher=>"Pub", :topic_id=>topic1.id
|
|
281
|
+
|
|
282
|
+
book1.topic = topic2
|
|
283
|
+
book2.topic = topic1
|
|
284
|
+
book3.topic = topic2
|
|
285
|
+
|
|
286
|
+
books = [ book1, book2, book3 ]
|
|
287
|
+
Book.import( books, :on_duplicate_key_update=>[ :topic_id ])
|
|
288
|
+
books.each{ |b| b.reload }
|
|
289
|
+
|
|
290
|
+
assert book1.topic_id == topic2.id, "wrong topic id for book1!"
|
|
291
|
+
assert book2.topic_id == topic1.id, "wrong topic id for book2!"
|
|
292
|
+
assert book3.topic_id == topic2.id, "wrong topic id for book3!"
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def test_import_should_not_update_created_at_or_created_on_columns_on_duplicate_keys_by_default
|
|
296
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
297
|
+
|
|
298
|
+
book1 = Book.create :title=>"book1", :author_name=>"Zach", :publisher=>"Pub"
|
|
299
|
+
book2 = Book.create :title=>"book2", :author_name=>"Mark", :publisher=>"Pub"
|
|
300
|
+
book3 = Book.create :title=>"book3", :author_name=>"Zach", :publisher=>"Pub"
|
|
301
|
+
books = [ book1, book2, book3 ]
|
|
302
|
+
created_at_arr = books.inject([]){ |arr,book| arr << book.created_at }
|
|
303
|
+
created_on_arr = books.inject([]){ |arr,book| arr << book.created_on }
|
|
304
|
+
|
|
305
|
+
Book.import books
|
|
306
|
+
books.each{ |b| b.reload }
|
|
307
|
+
|
|
308
|
+
created_at_arr.each_with_index do |time,i|
|
|
309
|
+
assert_equal time.to_s(:db), books[i].created_at.to_s(:db)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
created_on_arr.each_with_index do |time,i|
|
|
313
|
+
assert_equal time.to_s(:db), books[i].created_on.to_s(:db)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def test_import_should_update_updated_at_or_updated_on_columns_with_duplicate_keys_by_default
|
|
318
|
+
return unless Topic.supports_on_duplicate_key_update?
|
|
319
|
+
|
|
320
|
+
book1 = Book.create :title=>"book1", :author_name=>"Zach", :publisher=>"Pub"
|
|
321
|
+
book2 = Book.create :title=>"book2", :author_name=>"Mark", :publisher=>"Pub"
|
|
322
|
+
sleep 2
|
|
323
|
+
books = [ book1, book2 ]
|
|
324
|
+
updated_at_arr = books.inject([]){ |arr,book| arr << book.updated_at }
|
|
325
|
+
updated_on_arr = books.inject([]){ |arr,book| arr << book.updated_on }
|
|
326
|
+
Book.import books
|
|
327
|
+
books.each{ |b| b.reload }
|
|
328
|
+
|
|
329
|
+
updated_at_arr.each_with_index do |time,i|
|
|
330
|
+
assert time.to_f < books[i].updated_at.to_f
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
updated_on_arr.each_with_index do |time,i|
|
|
334
|
+
assert time.to_f < books[i].updated_on.to_f
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def test_import_without_timestamps
|
|
339
|
+
columns = %W{ id author_name }
|
|
340
|
+
values = []
|
|
341
|
+
values << [ 1, "Jerry Carter" ]
|
|
342
|
+
values << [ 2, "Chad Fowler" ]
|
|
343
|
+
|
|
344
|
+
expected_count = Topic.count
|
|
345
|
+
Topic.import( columns, values,
|
|
346
|
+
:validate=>false,
|
|
347
|
+
:timestamps=>false )
|
|
348
|
+
|
|
349
|
+
assert_equal expected_count+values.size, Topic.count, "#{ values.size } new records should have been created!"
|
|
350
|
+
assert_equal Topic.find( 1 ).created_at, nil, "created_at should be nil"
|
|
351
|
+
assert_equal Topic.find( 2 ).updated_at, nil, "updated_at should be nil"
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require File.expand_path( File.join( File.dirname( __FILE__ ), '..', 'test_helper' ))
|
|
2
|
+
|
|
3
|
+
class InsertSelectTest < TestCaseSuperClass
|
|
4
|
+
self.fixtures 'books'
|
|
5
|
+
if ActiveRecord::Base.connection.class.name =~ /sqlite/i
|
|
6
|
+
self.use_transactional_fixtures = false
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
#define the duplicate key update for mysql for testing
|
|
10
|
+
#add oracle, postgre, sqlite, etc when implemented
|
|
11
|
+
if ENV["ARE_DB"] == 'mysql'
|
|
12
|
+
DUPLICATE_UPDATE_STR = 'cart_items.updated_at=VALUES(`updated_at`), copies=VALUES(copies), book_id=VALUES(`book_id`)'
|
|
13
|
+
else
|
|
14
|
+
DUPLICATE_UPDATE_STR = [:updated_at, :copies, :book_id]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def setup
|
|
18
|
+
@connection = ActiveRecord::Base.connection
|
|
19
|
+
@conditions = ['author_name like :author_name', {:author_name => 'Terry Brooks'}]
|
|
20
|
+
@into_columns = [:book_id, :shopping_cart_id, :copies, :updated_at, :created_at]
|
|
21
|
+
@cart = ShoppingCart.create!(:name => 'My Shopping Cart')
|
|
22
|
+
@time = Time.now - 2.seconds
|
|
23
|
+
|
|
24
|
+
Topic.destroy_all
|
|
25
|
+
ShoppingCart.destroy_all
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def teardown
|
|
29
|
+
Topic.destroy_all
|
|
30
|
+
ShoppingCart.destroy_all
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#test simple insert select
|
|
34
|
+
def test_insert_select_should_import_data_from_one_model_into_another
|
|
35
|
+
assert_equal 0, Topic.count
|
|
36
|
+
|
|
37
|
+
timestamp = Time.now
|
|
38
|
+
Topic.insert_select(
|
|
39
|
+
:from => :book,
|
|
40
|
+
:select => ['title, author_name, ?', timestamp],
|
|
41
|
+
:into => [:title, :author_name, :updated_at])
|
|
42
|
+
|
|
43
|
+
books = Book.find :all, :order => 'title'
|
|
44
|
+
topics = Topic.find :all, :order => 'title'
|
|
45
|
+
|
|
46
|
+
assert_equal books.length, topics.length
|
|
47
|
+
|
|
48
|
+
topics.each_with_index {|topic, idx|
|
|
49
|
+
assert_equal topic.author_name, books[idx].author_name
|
|
50
|
+
assert_equal topic.title, books[idx].title
|
|
51
|
+
assert_equal topic.updated_at.to_s, timestamp.to_s
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_insert_select_should_import_data_from_one_model_into_another_ignoring_existing_data
|
|
56
|
+
time = Time.now - 4.seconds
|
|
57
|
+
#insert book data into cart
|
|
58
|
+
CartItem.insert_select(
|
|
59
|
+
:from => :book,
|
|
60
|
+
:select => ['books.id, ?, ?, ?, now()', @cart.to_param, 1, time],
|
|
61
|
+
:into => [:book_id, :shopping_cart_id, :copies, :updated_at, :created_at])
|
|
62
|
+
|
|
63
|
+
total = CartItem.count(:id, :conditions => ['shopping_cart_id = ? and updated_at = ?', @cart.to_param, time])
|
|
64
|
+
assert_equal 9, total, "Expecting 6 cart items. Instead got #{total}"
|
|
65
|
+
|
|
66
|
+
#insert the same data from book into the cart
|
|
67
|
+
CartItem.insert_select(:from => Book,
|
|
68
|
+
:select => ['books.id, ?, ?, ?, now()', @cart.to_param, 1, Time.now],
|
|
69
|
+
:into => 'cart_items.book_id, shopping_cart_id, copies, updated_at, created_at',
|
|
70
|
+
:ignore => true )
|
|
71
|
+
|
|
72
|
+
#ensure that the data has not changed
|
|
73
|
+
total = CartItem.count(:id, :conditions => ['shopping_cart_id = ? and updated_at = ?', @cart.to_param, time])
|
|
74
|
+
assert_equal 9, total, "Expecting 6 cart items. Instead got #{total}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_insert_select_should_import_data_from_one_model_into_another_updating_existing_data(options_one={}, options_two={})
|
|
78
|
+
fun_topic = Topic.create!(:title => 'Fun Books', :author_name => 'Big Bird')
|
|
79
|
+
ok_topic = Topic.create!(:title => 'OK Books', :author_name => 'sloth')
|
|
80
|
+
boring_topic = Topic.create!(:title => 'Boring Books', :author_name => 'Giraffe')
|
|
81
|
+
|
|
82
|
+
Book.update_all(['topic_id = ?', boring_topic])
|
|
83
|
+
Book.update_all(['topic_id = ?', fun_topic], 'books.id < 3')
|
|
84
|
+
Book.update_all(['topic_id = ?', ok_topic], 'books.id = 3')
|
|
85
|
+
|
|
86
|
+
CartItem.insert_select(
|
|
87
|
+
{:from => :book,
|
|
88
|
+
:select => ['books.id, ?, ?, ?, ?', @cart.to_param, 1, @time, @time],
|
|
89
|
+
:into => @into_columns,
|
|
90
|
+
:conditions => ['topics.title = :title', {:title => 'Fun Books'}],
|
|
91
|
+
:include => :topic }.merge(options_one))
|
|
92
|
+
|
|
93
|
+
validate_cart_items({:total => 2, :copies => 1 },
|
|
94
|
+
:conditions => ['topics.title in (?)', ['Fun Books']],
|
|
95
|
+
:include => { :book => :topic })
|
|
96
|
+
|
|
97
|
+
#insert select with on duplicate key update written as a string
|
|
98
|
+
new_time = Time.now
|
|
99
|
+
CartItem.insert_select(
|
|
100
|
+
{:from => :book,
|
|
101
|
+
:select => ['books.id, ?, ?, ?, ?', @cart.to_param, 2, new_time, new_time],
|
|
102
|
+
:into => @into_columns,
|
|
103
|
+
:conditions => ['topics.title in (?)', ['Fun Books', 'OK Books']],
|
|
104
|
+
:include => :topic ,
|
|
105
|
+
:on_duplicate_key_update => DUPLICATE_UPDATE_STR}.merge(options_two))
|
|
106
|
+
|
|
107
|
+
# 3 total items
|
|
108
|
+
assert_equal 3, CartItem.count
|
|
109
|
+
|
|
110
|
+
#2 fun books should have updated the updated_at and copies field
|
|
111
|
+
validate_cart_items({:total => 2, :updated_at => new_time, :copies => 2},
|
|
112
|
+
:conditions => ['topics.title in (?)', ['Fun Books']],
|
|
113
|
+
:include => { :book => :topic })
|
|
114
|
+
|
|
115
|
+
#1 ok book
|
|
116
|
+
validate_cart_items({:total => 1, :updated_at => new_time, :created_at => new_time, :copies => 2},
|
|
117
|
+
:conditions => ['topics.title in (?)', ['OK Books']],
|
|
118
|
+
:include => { :book => :topic })
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_insert_select_should_import_data_from_one_model_into_another_updating_existing_data_using_joins_and_limit
|
|
122
|
+
#use a join instead of include
|
|
123
|
+
options = {:include => nil, :joins => 'inner join topics on topics.id = books.topic_id', :limit => 4}
|
|
124
|
+
test_insert_select_should_import_data_from_one_model_into_another_updating_existing_data options, options
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#test insert select with ignore and duplicate options
|
|
128
|
+
def test_insert_select_should_import_data_from_one_model_into_another_updating_multiple_columns
|
|
129
|
+
|
|
130
|
+
@cart_copies = Book.count(:all, :conditions => @conditions)
|
|
131
|
+
assert @cart_copies > 0
|
|
132
|
+
|
|
133
|
+
@time = Time.now
|
|
134
|
+
CartItem.insert_select(
|
|
135
|
+
:from => :book,
|
|
136
|
+
:select => ['books.id, ?, ?, ?, ?', @cart.to_param, 1, @time, @time],
|
|
137
|
+
:conditions => @conditions,
|
|
138
|
+
:into => @into_columns)
|
|
139
|
+
|
|
140
|
+
validate_cart_items :total => @cart_copies, :copies => 1
|
|
141
|
+
|
|
142
|
+
#use on duplicate update
|
|
143
|
+
#this means that the book count should change to 2 and the updated time should be changed to new_time
|
|
144
|
+
new_time = Time.now
|
|
145
|
+
CartItem.insert_select(
|
|
146
|
+
:from => :book,
|
|
147
|
+
:select => ['books.id, :cart, :copies, :updated_at, :created_at', {:copies => 2, :cart => @cart, :created_at => new_time, :updated_at => new_time}],
|
|
148
|
+
:conditions => @conditions,
|
|
149
|
+
:into => @into_columns,
|
|
150
|
+
:on_duplicate_key_update => [:updated_at, :copies])
|
|
151
|
+
|
|
152
|
+
validate_cart_items :total => @cart_copies, :updated_at => new_time, :copies => 2
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
protected
|
|
156
|
+
|
|
157
|
+
def validate_cart_items(expected_values = {}, find_options = {})
|
|
158
|
+
|
|
159
|
+
vals = {:shopping_cart_id => @cart.to_param, :updated_at => @time, :created_at => @time, :copies => 1}.merge expected_values
|
|
160
|
+
total_count = vals.delete(:total)
|
|
161
|
+
|
|
162
|
+
items = CartItem.find(:all, find_options)
|
|
163
|
+
assert_equal(total_count, items.length, "Expecting #{total_count}, recieved #{items.length}") unless total_count.nil?
|
|
164
|
+
|
|
165
|
+
items.each do |item|
|
|
166
|
+
vals.each do |method, val|
|
|
167
|
+
actual = item.send method
|
|
168
|
+
assert_equal val.to_s, actual.to_s, "Expecting #{method} = #{val}. Instead got #{actual}"
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|