jorahood-ar-extensions 0.9.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|