ibm_db 2.5.27-x86-mingw32 → 2.6.0-x86-mingw32

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +5 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +264 -264
  8. data/ext/extconf_MacOS.rb +269 -0
  9. data/ext/ibm_db.c +1 -1
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/init.rb +41 -41
  12. data/lib/IBM_DB.rb +27 -3
  13. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3290 -3290
  14. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  15. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  16. data/lib/mswin32/ibm_db.rb +104 -20
  17. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  18. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  19. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/cases/adapter_test.rb +207 -207
  22. data/test/cases/associations/belongs_to_associations_test.rb +711 -711
  23. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
  24. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
  25. data/test/cases/associations/join_model_test.rb +743 -743
  26. data/test/cases/attribute_methods_test.rb +822 -822
  27. data/test/cases/base_test.rb +2133 -2133
  28. data/test/cases/calculations_test.rb +482 -482
  29. data/test/cases/migration_test.rb +2408 -2408
  30. data/test/cases/persistence_test.rb +642 -642
  31. data/test/cases/query_cache_test.rb +257 -257
  32. data/test/cases/relations_test.rb +1182 -1182
  33. data/test/cases/schema_dumper_test.rb +256 -256
  34. data/test/cases/transaction_callbacks_test.rb +300 -300
  35. data/test/cases/validations/uniqueness_validation_test.rb +299 -299
  36. data/test/cases/xml_serialization_test.rb +408 -408
  37. data/test/config.yml +154 -154
  38. data/test/connections/native_ibm_db/connection.rb +43 -43
  39. data/test/ibm_db_test.rb +24 -24
  40. data/test/models/warehouse_thing.rb +4 -4
  41. data/test/schema/schema.rb +751 -751
  42. metadata +31 -16
@@ -1,2408 +1,2408 @@
1
- require "cases/helper"
2
- require 'bigdecimal/util'
3
-
4
- require 'models/person'
5
- require 'models/topic'
6
- require 'models/developer'
7
-
8
- require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
9
- require MIGRATIONS_ROOT + "/rename/1_we_need_things"
10
- require MIGRATIONS_ROOT + "/rename/2_rename_things"
11
- require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
12
-
13
- if ActiveRecord::Base.connection.supports_migrations?
14
- class BigNumber < ActiveRecord::Base; end
15
-
16
- class Reminder < ActiveRecord::Base; end
17
-
18
- class Thing < ActiveRecord::Base; end
19
-
20
- class ActiveRecord::Migration
21
- class << self
22
- attr_accessor :message_count
23
- end
24
-
25
- def puts(text="")
26
- ActiveRecord::Migration.message_count ||= 0
27
- ActiveRecord::Migration.message_count += 1
28
- end
29
- end
30
-
31
- class MigrationTableAndIndexTest < ActiveRecord::TestCase
32
- def test_add_schema_info_respects_prefix_and_suffix
33
- conn = ActiveRecord::Base.connection
34
-
35
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
36
- # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
37
- ActiveRecord::Base.table_name_prefix = 'p_'
38
- ActiveRecord::Base.table_name_suffix = '_s'
39
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
40
-
41
- conn.initialize_schema_migrations_table
42
-
43
- assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
44
- ensure
45
- ActiveRecord::Base.table_name_prefix = ""
46
- ActiveRecord::Base.table_name_suffix = ""
47
- end
48
- end
49
-
50
- class MigrationTest < ActiveRecord::TestCase
51
- self.use_transactional_fixtures = false
52
-
53
- if (current_adapter?(:IBM_DBAdapter))
54
- #Rename is supported only for server zOS 9 , DB2 COBRA and Informix
55
- server_type = ActiveRecord::Base.connection.servertype.class.name
56
- @ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
57
- server_type.class.name.include?('::IBM_IDS') ||
58
- (server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
59
- end
60
-
61
- fixtures :people
62
-
63
- def setup
64
- ActiveRecord::Migration.verbose = true
65
- ActiveRecord::Migration.message_count = 0
66
- end
67
-
68
- def teardown
69
- ActiveRecord::Base.connection.initialize_schema_migrations_table
70
- ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
71
-
72
- %w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table|
73
- Thing.connection.drop_table(table) rescue nil
74
- end
75
- Thing.reset_column_information
76
-
77
- %w(reminders people_reminders prefix_reminders_suffix).each do |table|
78
- Reminder.connection.drop_table(table) rescue nil
79
- end
80
- Reminder.reset_column_information
81
-
82
- %w(last_name key bio age height wealth birthday favorite_day
83
- moment_of_truth male administrator funny).each do |column|
84
- Person.connection.remove_column('people', column) rescue nil
85
- end
86
- Person.connection.remove_column("people", "first_name") rescue nil
87
- Person.connection.remove_column("people", "middle_name") rescue nil
88
- Person.connection.add_column("people", "first_name", :string, :limit => 40)
89
- Person.reset_column_information
90
- end
91
-
92
- def test_add_index
93
- # Limit size of last_name and key columns to support Firebird index limitations
94
- Person.connection.add_column "people", "last_name", :string, :limit => 100
95
- Person.connection.add_column "people", "key", :string, :limit => 100
96
- Person.connection.add_column "people", "administrator", :boolean
97
-
98
- assert_nothing_raised { Person.connection.add_index("people", "last_name") }
99
- assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
100
-
101
- # Orcl nds shrt indx nms. Sybs 2.
102
- # OpenBase does not have named indexes. You must specify a single column name
103
- unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
104
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
105
- assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
106
- # Oracle adapter cannot have specified index name larger than 30 characters
107
- # Oracle adapter is shortening index name when just column list is given
108
- unless current_adapter?(:OracleAdapter)
109
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
110
- assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) }
111
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
112
- assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
113
- end
114
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
115
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
116
- assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
117
- assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
118
- assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
119
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
120
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
121
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
122
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
123
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
124
- end
125
-
126
- # quoting
127
- # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
128
- # OpenBase does not have named indexes. You must specify a single column name
129
- unless current_adapter?(:OpenBaseAdapter)
130
- unless current_adapter?(:IBM_DBAdapter)
131
- Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
132
- else
133
- Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'first_name'}"
134
- end
135
- assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
136
- assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
137
- end
138
-
139
- # Sybase adapter does not support indexes on :boolean columns
140
- # OpenBase does not have named indexes. You must specify a single column
141
- unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
142
- assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
143
- assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
144
- end
145
-
146
- # Selected adapters support index sort order
147
- if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
148
- assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) }
149
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
150
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) }
151
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
152
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) }
153
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
154
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) }
155
- assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
156
- end
157
- end
158
-
159
- def test_index_symbol_names
160
- assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name }
161
- assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
162
- assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name }
163
- assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
164
- end
165
-
166
- def test_add_index_length_limit
167
- good_index_name = 'x' * Person.connection.index_name_length
168
- too_long_index_name = good_index_name + 'x'
169
- assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) }
170
- assert !Person.connection.index_name_exists?("people", too_long_index_name, false)
171
- assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) }
172
- assert Person.connection.index_name_exists?("people", good_index_name, false)
173
- Person.connection.remove_index("people", :name => good_index_name)
174
- end
175
-
176
- def test_add_index_attribute_length_limit
177
- Person.connection.add_index :people, [:first_name, :primary_contact_id], :length => {:first_name => 10, :primary_contact_id => nil}, :name => "attribute_length"
178
- assert Person.connection.index_exists?(:people, [:first_name, :primary_contact_id], :name => "attribute_length")
179
- ensure
180
- Person.connection.remove_index(:people, :name => "attribute_length")
181
- end
182
-
183
- def test_remove_nonexistent_index
184
- # we do this by name, so OpenBase is a wash as noted above
185
- unless current_adapter?(:OpenBaseAdapter)
186
- assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") }
187
- end
188
- end
189
-
190
- def test_rename_index
191
- unless current_adapter?(:OpenBaseAdapter)
192
- # keep the names short to make Oracle and similar behave
193
- Person.connection.add_index('people', [:first_name], :name => 'old_idx')
194
- assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') }
195
- # if the adapter doesn't support the indexes call, pick defaults that let the test pass
196
- assert !Person.connection.index_name_exists?('people', 'old_idx', false)
197
- assert Person.connection.index_name_exists?('people', 'new_idx', true)
198
- end
199
- end
200
-
201
- def test_double_add_index
202
- unless current_adapter?(:OpenBaseAdapter)
203
- Person.connection.add_index('people', [:first_name], :name => 'some_idx')
204
- assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') }
205
- end
206
- end
207
-
208
- def test_index_exists
209
- Person.connection.create_table :testings do |t|
210
- t.column :foo, :string, :limit => 100
211
- t.column :bar, :string, :limit => 100
212
- end
213
- Person.connection.add_index :testings, :foo
214
-
215
- assert Person.connection.index_exists?(:testings, :foo)
216
- assert !Person.connection.index_exists?(:testings, :bar)
217
- ensure
218
- Person.connection.drop_table :testings rescue nil
219
- end
220
-
221
- def test_index_exists_on_multiple_columns
222
- Person.connection.create_table :testings do |t|
223
- t.column :foo, :string, :limit => 100
224
- t.column :bar, :string, :limit => 100
225
- end
226
- Person.connection.add_index :testings, [:foo, :bar]
227
-
228
- assert Person.connection.index_exists?(:testings, [:foo, :bar])
229
- ensure
230
- Person.connection.drop_table :testings rescue nil
231
- end
232
-
233
- def test_unique_index_exists
234
- Person.connection.create_table :testings do |t|
235
- t.column :foo, :string, :limit => 100
236
- end
237
- Person.connection.add_index :testings, :foo, :unique => true
238
-
239
- assert Person.connection.index_exists?(:testings, :foo, :unique => true)
240
- ensure
241
- Person.connection.drop_table :testings rescue nil
242
- end
243
-
244
- def test_named_index_exists
245
- Person.connection.create_table :testings do |t|
246
- t.column :foo, :string, :limit => 100
247
- end
248
- Person.connection.add_index :testings, :foo, :name => "custom_index_name"
249
-
250
- assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name")
251
- ensure
252
- Person.connection.drop_table :testings rescue nil
253
- end
254
-
255
- def testing_table_with_only_foo_attribute
256
- Person.connection.create_table :testings, :id => false do |t|
257
- t.column :foo, :string
258
- end
259
-
260
- yield Person.connection
261
- ensure
262
- Person.connection.drop_table :testings rescue nil
263
- end
264
- protected :testing_table_with_only_foo_attribute
265
-
266
- def test_create_table_without_id
267
- testing_table_with_only_foo_attribute do |connection|
268
- assert_equal connection.columns(:testings).size, 1
269
- end
270
- end
271
-
272
- unless current_adapter?(:IBM_DBAdapter)
273
- # For DB2: Cannot add a primary key to a table with some rows already in it as it violates the unique constraint
274
- # Secondly GENERATED BY DEFAULT AS IDENTITY cannot be applied in a alter table command.
275
- # as this will be wrong sql syntax for DB
276
- def test_add_column_with_primary_key_attribute
277
- testing_table_with_only_foo_attribute do |connection|
278
- assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
279
- assert_equal connection.columns(:testings).size, 2
280
- end
281
- end
282
- end
283
-
284
- def test_create_table_adds_id
285
- Person.connection.create_table :testings do |t|
286
- t.column :foo, :string
287
- end
288
-
289
- assert_equal %w(foo id),
290
- Person.connection.columns(:testings).map { |c| c.name }.sort
291
- ensure
292
- Person.connection.drop_table :testings rescue nil
293
- end
294
-
295
- def test_create_table_with_not_null_column
296
- assert_nothing_raised do
297
- Person.connection.create_table :testings do |t|
298
- t.column :foo, :string, :null => false
299
- end
300
- end
301
-
302
- assert_raise(ActiveRecord::StatementInvalid) do
303
- Person.connection.execute "insert into testings (foo) values (NULL)"
304
- end
305
- ensure
306
- Person.connection.drop_table :testings rescue nil
307
- end
308
-
309
- def test_create_table_with_defaults
310
- # MySQL doesn't allow defaults on TEXT or BLOB columns.
311
- mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
312
-
313
- Person.connection.create_table :testings do |t|
314
- t.column :one, :string, :default => "hello"
315
- t.column :two, :boolean, :default => true
316
- t.column :three, :boolean, :default => false
317
- t.column :four, :integer, :default => 1
318
- t.column :five, :text, :default => "hello" unless mysql
319
- end
320
-
321
- columns = Person.connection.columns(:testings)
322
- one = columns.detect { |c| c.name == "one" }
323
- two = columns.detect { |c| c.name == "two" }
324
- three = columns.detect { |c| c.name == "three" }
325
- four = columns.detect { |c| c.name == "four" }
326
- five = columns.detect { |c| c.name == "five" } unless mysql
327
-
328
- assert_equal "hello", one.default
329
- assert_equal true, two.default
330
- assert_equal false, three.default
331
- assert_equal 1, four.default
332
- assert_equal "hello", five.default unless mysql
333
-
334
- ensure
335
- Person.connection.drop_table :testings rescue nil
336
- end
337
-
338
- def test_create_table_with_limits
339
- assert_nothing_raised do
340
- Person.connection.create_table :testings do |t|
341
- t.column :foo, :string, :limit => 255
342
-
343
- t.column :default_int, :integer
344
-
345
- t.column :one_int, :integer, :limit => 1
346
- t.column :four_int, :integer, :limit => 4
347
- t.column :eight_int, :integer, :limit => 8
348
- t.column :eleven_int, :integer, :limit => 11
349
- end
350
- end
351
-
352
- columns = Person.connection.columns(:testings)
353
- foo = columns.detect { |c| c.name == "foo" }
354
- assert_equal 255, foo.limit
355
-
356
- default = columns.detect { |c| c.name == "default_int" }
357
- one = columns.detect { |c| c.name == "one_int" }
358
- four = columns.detect { |c| c.name == "four_int" }
359
- eight = columns.detect { |c| c.name == "eight_int" }
360
- eleven = columns.detect { |c| c.name == "eleven_int" }
361
-
362
- if current_adapter?(:PostgreSQLAdapter)
363
- assert_equal 'integer', default.sql_type
364
- assert_equal 'smallint', one.sql_type
365
- assert_equal 'integer', four.sql_type
366
- assert_equal 'bigint', eight.sql_type
367
- assert_equal 'integer', eleven.sql_type
368
- elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
369
- assert_match 'int(11)', default.sql_type
370
- assert_match 'tinyint', one.sql_type
371
- assert_match 'int', four.sql_type
372
- assert_match 'bigint', eight.sql_type
373
- assert_match 'int(11)', eleven.sql_type
374
- elsif current_adapter?(:OracleAdapter)
375
- assert_equal 'NUMBER(38)', default.sql_type
376
- assert_equal 'NUMBER(1)', one.sql_type
377
- assert_equal 'NUMBER(4)', four.sql_type
378
- assert_equal 'NUMBER(8)', eight.sql_type
379
- end
380
- ensure
381
- Person.connection.drop_table :testings rescue nil
382
- end
383
-
384
- def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
385
- ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
386
-
387
- Person.connection.create_table :testings do |t|
388
- t.column :foo, :string
389
- end
390
-
391
- assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
392
- ensure
393
- Person.connection.drop_table :testings rescue nil
394
- ActiveRecord::Base.primary_key_prefix_type = nil
395
- end
396
-
397
- def test_create_table_with_primary_key_prefix_as_table_name
398
- ActiveRecord::Base.primary_key_prefix_type = :table_name
399
-
400
- Person.connection.create_table :testings do |t|
401
- t.column :foo, :string
402
- end
403
-
404
- assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
405
- ensure
406
- Person.connection.drop_table :testings rescue nil
407
- ActiveRecord::Base.primary_key_prefix_type = nil
408
- end
409
-
410
- def test_create_table_with_force_true_does_not_drop_nonexisting_table
411
- if Person.connection.table_exists?(:testings2)
412
- Person.connection.drop_table :testings2
413
- end
414
-
415
- # using a copy as we need the drop_table method to
416
- # continue to work for the ensure block of the test
417
- temp_conn = Person.connection.dup
418
- temp_conn.expects(:drop_table).never
419
- temp_conn.create_table :testings2, :force => true do |t|
420
- t.column :foo, :string
421
- end
422
- ensure
423
- Person.connection.drop_table :testings2 rescue nil
424
- end
425
-
426
- def test_create_table_with_timestamps_should_create_datetime_columns
427
- table_name = :testings
428
-
429
- Person.connection.create_table table_name do |t|
430
- t.timestamps
431
- end
432
- created_columns = Person.connection.columns(table_name)
433
-
434
- created_at_column = created_columns.detect {|c| c.name == 'created_at' }
435
- updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
436
-
437
- assert !created_at_column.null
438
- assert !updated_at_column.null
439
- ensure
440
- Person.connection.drop_table table_name rescue nil
441
- end
442
-
443
- def test_create_table_with_timestamps_should_create_datetime_columns_with_options
444
- table_name = :testings
445
-
446
- Person.connection.create_table table_name do |t|
447
- t.timestamps :null => false
448
- end
449
- created_columns = Person.connection.columns(table_name)
450
-
451
- created_at_column = created_columns.detect {|c| c.name == 'created_at' }
452
- updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
453
-
454
- assert !created_at_column.null
455
- assert !updated_at_column.null
456
- ensure
457
- Person.connection.drop_table table_name rescue nil
458
- end
459
-
460
- def test_create_table_without_a_block
461
- table_name = :testings
462
- Person.connection.create_table table_name
463
- ensure
464
- Person.connection.drop_table table_name rescue nil
465
- end
466
-
467
- # Sybase, and SQLite3 will not allow you to add a NOT NULL
468
- # column to a table without a default value.
469
- unless current_adapter?(:SybaseAdapter, :SQLite3Adapter, :IBM_DBAdapter)
470
- def test_add_column_not_null_without_default
471
- Person.connection.create_table :testings do |t|
472
- t.column :foo, :string
473
- end
474
- Person.connection.add_column :testings, :bar, :string, :null => false
475
-
476
- assert_raise(ActiveRecord::StatementInvalid) do
477
- Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
478
- end
479
- ensure
480
- Person.connection.drop_table :testings rescue nil
481
- end
482
- end
483
-
484
- def test_add_column_not_null_with_default
485
- Person.connection.create_table :testings do |t|
486
- t.column :foo, :string
487
- end
488
-
489
- con = Person.connection
490
- Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
491
- Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
492
- Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
493
- assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
494
-
495
- assert_raise(ActiveRecord::StatementInvalid) do
496
- unless current_adapter?(:OpenBaseAdapter)
497
- Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
498
- else
499
- Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)",
500
- "Testing Insert","id",2)
501
- end
502
- end
503
- ensure
504
- Person.connection.drop_table :testings rescue nil
505
- end
506
-
507
- # We specifically do a manual INSERT here, and then test only the SELECT
508
- # functionality. This allows us to more easily catch INSERT being broken,
509
- # but SELECT actually working fine.
510
- def test_native_decimal_insert_manual_vs_automatic
511
- correct_value = '0012345678901234567890.0123456789'.to_d
512
-
513
- Person.delete_all
514
- Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
515
- Person.reset_column_information
516
-
517
- # Do a manual insertion
518
- if current_adapter?(:OracleAdapter)
519
- Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
520
- elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
521
- Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
522
- elsif current_adapter?(:PostgreSQLAdapter)
523
- Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
524
- elsif current_adapter?(:IBM_DBAdapter)
525
- Person.connection.execute "insert into people (wealth, created_at, updated_at, lock_version, first_name) values (12345678901234567890.0123456789, CURRENT TIMESTAMP, CURRENT TIMESTAMP, 0, 'Jim')"
526
- else
527
- Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
528
- end
529
-
530
- # SELECT
531
- row = Person.find(:first)
532
- assert_kind_of BigDecimal, row.wealth
533
-
534
- # If this assert fails, that means the SELECT is broken!
535
- unless current_adapter?(:SQLite3Adapter)
536
- assert_equal correct_value, row.wealth
537
- end
538
-
539
- # Reset to old state
540
- Person.delete_all
541
-
542
- # Now use the Rails insertion
543
- unless current_adapter?(:IBM_DBAdapter)
544
- assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
545
- else
546
- # First_name is a not null column, hence ensure a value is specified
547
- assert_nothing_raised { Person.create ({:wealth => BigDecimal.new("12345678901234567890.0123456789"), :first_name => "James"}) }
548
- end
549
-
550
- # SELECT
551
- row = Person.find(:first)
552
- assert_kind_of BigDecimal, row.wealth
553
-
554
- # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
555
- unless current_adapter?(:SQLite3Adapter)
556
- assert_equal correct_value, row.wealth
557
- end
558
-
559
- # Reset to old state
560
- Person.connection.del_column "people", "wealth" rescue nil
561
- Person.reset_column_information
562
- end
563
-
564
- def test_add_column_with_precision_and_scale
565
- Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
566
- Person.reset_column_information
567
-
568
- wealth_column = Person.columns_hash['wealth']
569
- assert_equal 9, wealth_column.precision
570
- assert_equal 7, wealth_column.scale
571
- end
572
-
573
- # Test SQLite adapter specifically for decimal types with precision and scale
574
- # attributes, since these need to be maintained in schema but aren't actually
575
- # used in SQLite itself
576
- if current_adapter?(:SQLite3Adapter)
577
- def test_change_column_with_new_precision_and_scale
578
- Person.delete_all
579
- Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
580
- Person.reset_column_information
581
-
582
- Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8
583
- Person.reset_column_information
584
-
585
- wealth_column = Person.columns_hash['wealth']
586
- assert_equal 12, wealth_column.precision
587
- assert_equal 8, wealth_column.scale
588
- end
589
-
590
- def test_change_column_preserve_other_column_precision_and_scale
591
- Person.delete_all
592
- Person.connection.add_column 'people', 'last_name', :string
593
- Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
594
- Person.reset_column_information
595
-
596
- wealth_column = Person.columns_hash['wealth']
597
- assert_equal 9, wealth_column.precision
598
- assert_equal 7, wealth_column.scale
599
-
600
- Person.connection.change_column 'people', 'last_name', :string, :null => false
601
- Person.reset_column_information
602
-
603
- wealth_column = Person.columns_hash['wealth']
604
- assert_equal 9, wealth_column.precision
605
- assert_equal 7, wealth_column.scale
606
- end
607
- end
608
-
609
- def test_native_types
610
- Person.delete_all
611
- Person.connection.add_column "people", "last_name", :string
612
- Person.connection.add_column "people", "bio", :text
613
- Person.connection.add_column "people", "age", :integer
614
- Person.connection.add_column "people", "height", :float
615
- Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
616
- Person.connection.add_column "people", "birthday", :datetime
617
- Person.connection.add_column "people", "favorite_day", :date
618
- Person.connection.add_column "people", "moment_of_truth", :datetime
619
- Person.connection.add_column "people", "male", :boolean
620
- Person.reset_column_information
621
-
622
- assert_nothing_raised do
623
- Person.create :first_name => 'bob', :last_name => 'bobsen',
624
- :bio => "I was born ....", :age => 18, :height => 1.78,
625
- :wealth => BigDecimal.new("12345678901234567890.0123456789"),
626
- :birthday => 18.years.ago, :favorite_day => 10.days.ago,
627
- :moment_of_truth => "1782-10-10 21:40:18", :male => true
628
- end
629
-
630
- bob = Person.find(:first)
631
- assert_equal 'bob', bob.first_name
632
- assert_equal 'bobsen', bob.last_name
633
- assert_equal "I was born ....", bob.bio
634
- assert_equal 18, bob.age
635
-
636
- # Test for 30 significant digits (beyond the 16 of float), 10 of them
637
- # after the decimal place.
638
-
639
- unless current_adapter?(:SQLite3Adapter)
640
- assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
641
- end
642
-
643
- assert_equal true, bob.male?
644
-
645
- assert_equal String, bob.first_name.class
646
- assert_equal String, bob.last_name.class
647
- assert_equal String, bob.bio.class
648
- assert_equal Fixnum, bob.age.class
649
- assert_equal Time, bob.birthday.class
650
-
651
- if current_adapter?(:OracleAdapter, :SybaseAdapter)
652
- # Sybase, and Oracle don't differentiate between date/time
653
- assert_equal Time, bob.favorite_day.class
654
- else
655
- assert_equal Date, bob.favorite_day.class
656
- end
657
-
658
- # Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column
659
- # therefore no timezone change is done afterwards when default timezone is changed
660
- unless current_adapter?(:OracleAdapter)
661
- # Test DateTime column and defaults, including timezone.
662
- # FIXME: moment of truth may be Time on 64-bit platforms.
663
- if bob.moment_of_truth.is_a?(DateTime)
664
-
665
- with_env_tz 'US/Eastern' do
666
- bob.reload
667
- assert_equal DateTime.local_offset, bob.moment_of_truth.offset
668
- assert_not_equal 0, bob.moment_of_truth.offset
669
- assert_not_equal "Z", bob.moment_of_truth.zone
670
- # US/Eastern is -5 hours from GMT
671
- assert_equal Rational(-5, 24), bob.moment_of_truth.offset
672
- assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM
673
- assert_equal DateTime::ITALY, bob.moment_of_truth.start
674
- end
675
- end
676
- end
677
-
678
- assert_instance_of TrueClass, bob.male?
679
- assert_kind_of BigDecimal, bob.wealth
680
- end
681
-
682
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
683
- def test_unabstracted_database_dependent_types
684
- Person.delete_all
685
-
686
- ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
687
- Person.reset_column_information
688
- assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type)
689
- ensure
690
- ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
691
- end
692
- end
693
-
694
- def test_add_remove_single_field_using_string_arguments
695
- assert !Person.column_methods_hash.include?(:last_name)
696
-
697
- ActiveRecord::Migration.add_column 'people', 'last_name', :string
698
-
699
- Person.reset_column_information
700
- assert Person.column_methods_hash.include?(:last_name)
701
-
702
- ActiveRecord::Migration.remove_column 'people', 'last_name'
703
-
704
- Person.reset_column_information
705
- assert !Person.column_methods_hash.include?(:last_name)
706
- end
707
-
708
- def test_add_remove_single_field_using_symbol_arguments
709
- assert !Person.column_methods_hash.include?(:last_name)
710
-
711
- ActiveRecord::Migration.add_column :people, :last_name, :string
712
-
713
- Person.reset_column_information
714
- assert Person.column_methods_hash.include?(:last_name)
715
-
716
- ActiveRecord::Migration.remove_column :people, :last_name
717
-
718
- Person.reset_column_information
719
- assert !Person.column_methods_hash.include?(:last_name)
720
- end
721
-
722
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
723
- def testing_table_for_positioning
724
- Person.connection.create_table :testings, :id => false do |t|
725
- t.column :first, :integer
726
- t.column :second, :integer
727
- t.column :third, :integer
728
- end
729
-
730
- yield Person.connection
731
- ensure
732
- Person.connection.drop_table :testings rescue nil
733
- end
734
- protected :testing_table_for_positioning
735
-
736
- def test_column_positioning
737
- testing_table_for_positioning do |conn|
738
- assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
739
- end
740
- end
741
-
742
- def test_add_column_with_positioning
743
- testing_table_for_positioning do |conn|
744
- conn.add_column :testings, :new_col, :integer
745
- assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
746
- end
747
- testing_table_for_positioning do |conn|
748
- conn.add_column :testings, :new_col, :integer, :first => true
749
- assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
750
- end
751
- testing_table_for_positioning do |conn|
752
- conn.add_column :testings, :new_col, :integer, :after => :first
753
- assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
754
- end
755
- end
756
-
757
- def test_change_column_with_positioning
758
- testing_table_for_positioning do |conn|
759
- conn.change_column :testings, :second, :integer, :first => true
760
- assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
761
- end
762
- testing_table_for_positioning do |conn|
763
- conn.change_column :testings, :second, :integer, :after => :third
764
- assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
765
- end
766
- end
767
- end
768
-
769
- if(!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
770
- def test_add_rename
771
- Person.delete_all
772
-
773
- begin
774
- Person.connection.add_column "people", "girlfriend", :string
775
- Person.reset_column_information
776
- Person.create :girlfriend => 'bobette'
777
-
778
- Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
779
-
780
- Person.reset_column_information
781
- bob = Person.find(:first)
782
-
783
- assert_equal "bobette", bob.exgirlfriend
784
- ensure
785
- Person.connection.remove_column("people", "girlfriend") rescue nil
786
- Person.connection.remove_column("people", "exgirlfriend") rescue nil
787
- end
788
-
789
- end
790
-
791
- def test_rename_column_using_symbol_arguments
792
- begin
793
- names_before = Person.find(:all).map(&:first_name)
794
- Person.connection.rename_column :people, :first_name, :nick_name
795
- Person.reset_column_information
796
- assert Person.column_names.include?("nick_name")
797
- assert_equal names_before, Person.find(:all).map(&:nick_name)
798
- ensure
799
- Person.connection.remove_column("people","nick_name")
800
- Person.connection.add_column("people","first_name", :string)
801
- end
802
- end
803
-
804
- def test_rename_column
805
- begin
806
- names_before = Person.find(:all).map(&:first_name)
807
- Person.connection.rename_column "people", "first_name", "nick_name"
808
- Person.reset_column_information
809
- assert Person.column_names.include?("nick_name")
810
- assert_equal names_before, Person.find(:all).map(&:nick_name)
811
- ensure
812
- Person.connection.remove_column("people","nick_name")
813
- Person.connection.add_column("people","first_name", :string)
814
- end
815
- end
816
-
817
- def test_rename_column_preserves_default_value_not_null
818
- begin
819
- default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
820
- assert_equal 70000, default_before
821
- Developer.connection.rename_column "developers", "salary", "anual_salary"
822
- Developer.reset_column_information
823
- assert Developer.column_names.include?("anual_salary")
824
- default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
825
- assert_equal 70000, default_after
826
- ensure
827
- Developer.connection.rename_column "developers", "anual_salary", "salary"
828
- Developer.reset_column_information
829
- end
830
- end
831
-
832
- def test_rename_nonexistent_column
833
- ActiveRecord::Base.connection.create_table(:hats) do |table|
834
- table.column :hat_name, :string, :default => nil
835
- end
836
- exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
837
- ActiveRecord::StatementInvalid
838
- else
839
- ActiveRecord::ActiveRecordError
840
- end
841
- assert_raise(exception) do
842
- Person.connection.rename_column "hats", "nonexistent", "should_fail"
843
- end
844
- ensure
845
- ActiveRecord::Base.connection.drop_table(:hats)
846
- end
847
-
848
- def test_rename_column_with_sql_reserved_word
849
- begin
850
- assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
851
- Person.reset_column_information
852
- assert Person.column_names.include?("group")
853
- ensure
854
- Person.connection.remove_column("people", "group") rescue nil
855
- Person.connection.add_column("people", "first_name", :string) rescue nil
856
- end
857
- end
858
- end
859
-
860
- unless current_adapter?(:IBM_DBAdapter)
861
- def test_rename_column_with_an_index
862
- ActiveRecord::Base.connection.create_table(:hats) do |table|
863
- table.column :hat_name, :string, :limit => 100
864
- table.column :hat_size, :integer
865
- end
866
- Person.connection.add_index :hats, :hat_name
867
- assert_nothing_raised do
868
- Person.connection.rename_column "hats", "hat_name", "name"
869
- end
870
- ensure
871
- ActiveRecord::Base.connection.drop_table(:hats)
872
- end
873
- end
874
-
875
- def test_remove_column_with_index
876
- ActiveRecord::Base.connection.create_table(:hats) do |table|
877
- table.column :hat_name, :string, :limit => 100
878
- table.column :hat_size, :integer
879
- end
880
- ActiveRecord::Base.connection.add_index "hats", "hat_size"
881
-
882
- assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
883
- ensure
884
- ActiveRecord::Base.connection.drop_table(:hats)
885
- end
886
-
887
- def test_remove_column_with_multi_column_index
888
- ActiveRecord::Base.connection.create_table(:hats) do |table|
889
- table.column :hat_name, :string, :limit => 100
890
- table.column :hat_size, :integer
891
- table.column :hat_style, :string, :limit => 100
892
- end
893
- ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
894
-
895
- assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
896
- ensure
897
- ActiveRecord::Base.connection.drop_table(:hats)
898
- end
899
-
900
- def test_remove_column_no_second_parameter_raises_exception
901
- assert_raise(ArgumentError) { Person.connection.remove_column("funny") }
902
- end
903
-
904
- def test_change_type_of_not_null_column
905
- assert_nothing_raised do
906
- unless current_adapter?(:IBM_DBAdapter)
907
- Topic.connection.change_column "topics", "written_on", :datetime, :null => false
908
- else
909
- Topic.connection.change_column_null "topics", "written_on", false
910
- end
911
- Topic.reset_column_information
912
-
913
- unless current_adapter?(:IBM_DBAdapter)
914
- Topic.connection.change_column "topics", "written_on", :datetime, :null => false
915
- else
916
- Topic.connection.change_column_null "topics", "written_on", false
917
- end
918
- Topic.reset_column_information
919
-
920
- unless current_adapter?(:IBM_DBAdapter)
921
- Topic.connection.change_column "topics", "written_on", :datetime, :null => true
922
- else
923
- Topic.connection.change_column_null "topics", "written_on", true
924
- end
925
-
926
- Topic.reset_column_information
927
- end
928
- end
929
-
930
- if current_adapter?(:SQLite3Adapter)
931
- def test_rename_table_for_sqlite_should_work_with_reserved_words
932
- begin
933
- assert_nothing_raised do
934
- ActiveRecord::Base.connection.rename_table :references, :old_references
935
- ActiveRecord::Base.connection.create_table :octopuses do |t|
936
- t.column :url, :string
937
- end
938
- end
939
-
940
- assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references }
941
-
942
- # Using explicit id in insert for compatibility across all databases
943
- con = ActiveRecord::Base.connection
944
- assert_nothing_raised do
945
- con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')"
946
- end
947
- assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1")
948
-
949
- ensure
950
- ActiveRecord::Base.connection.drop_table :references
951
- ActiveRecord::Base.connection.rename_table :old_references, :references
952
- end
953
- end
954
- end
955
-
956
- def test_rename_table
957
- begin
958
- ActiveRecord::Base.connection.create_table :octopuses do |t|
959
- t.column :url, :string
960
- end
961
- ActiveRecord::Base.connection.rename_table :octopuses, :octopi
962
-
963
- # Using explicit id in insert for compatibility across all databases
964
- con = ActiveRecord::Base.connection
965
- con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
966
- assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
967
- con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
968
-
969
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
970
-
971
- ensure
972
- ActiveRecord::Base.connection.drop_table :octopuses rescue nil
973
- ActiveRecord::Base.connection.drop_table :octopi rescue nil
974
- end
975
- end
976
-
977
- def test_change_column_nullability
978
- Person.delete_all
979
- Person.connection.add_column "people", "funny", :boolean
980
- Person.reset_column_information
981
- assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
982
- unless current_adapter?(:IBM_DBAdapter)
983
- Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
984
- else
985
- Person.connection.change_column_null "people", "funny",false
986
- end
987
- Person.reset_column_information
988
- assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
989
- unless current_adapter?(:IBM_DBAdapter)
990
- Person.connection.change_column "people", "funny", :boolean, :null => true
991
- else
992
- Person.connection.change_column_null "people", "funny",true
993
- end
994
- Person.reset_column_information
995
- assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
996
- end
997
-
998
- def test_rename_table_with_an_index
999
- begin
1000
- ActiveRecord::Base.connection.create_table :octopuses do |t|
1001
- t.column :url, :string
1002
- end
1003
- ActiveRecord::Base.connection.add_index :octopuses, :url
1004
-
1005
- ActiveRecord::Base.connection.rename_table :octopuses, :octopi
1006
-
1007
- # Using explicit id in insert for compatibility across all databases
1008
- con = ActiveRecord::Base.connection
1009
- con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
1010
- assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
1011
- con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
1012
-
1013
- assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
1014
- assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
1015
- ensure
1016
- ActiveRecord::Base.connection.drop_table :octopuses rescue nil
1017
- ActiveRecord::Base.connection.drop_table :octopi rescue nil
1018
- end
1019
- end
1020
-
1021
- unless current_adapter?(:IBM_DBAdapter)
1022
- # Cannot convert from type integer to varchar.
1023
- # Safe to not run this test as add_column will be covered in other test cases
1024
- def test_change_column
1025
- Person.connection.add_column 'people', 'age', :integer
1026
- label = "test_change_column Columns"
1027
- old_columns = Person.connection.columns(Person.table_name, label)
1028
- assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
1029
-
1030
- assert_nothing_raised { Person.connection.change_column "people", "age", :string }
1031
-
1032
- new_columns = Person.connection.columns(Person.table_name, label)
1033
- assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
1034
- assert new_columns.find { |c| c.name == 'age' and c.type == :string }
1035
-
1036
- old_columns = Topic.connection.columns(Topic.table_name, label)
1037
- assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
1038
- assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
1039
- new_columns = Topic.connection.columns(Topic.table_name, label)
1040
- assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
1041
- assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
1042
- assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
1043
- end
1044
- end
1045
-
1046
- def test_change_column_with_nil_default
1047
- Person.connection.add_column "people", "contributor", :boolean, :default => true
1048
- Person.reset_column_information
1049
- assert Person.new.contributor?
1050
-
1051
- unless current_adapter?(:IBM_DBAdapter)
1052
- assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
1053
- else
1054
- assert_nothing_raised { Person.connection.change_column_default "people", "contributor", nil }
1055
- end
1056
- Person.reset_column_information
1057
- assert !Person.new.contributor?
1058
- assert_nil Person.new.contributor
1059
- ensure
1060
- Person.connection.remove_column("people", "contributor") rescue nil
1061
- end
1062
-
1063
- def test_change_column_with_new_default
1064
- Person.connection.add_column "people", "administrator", :boolean, :default => true
1065
- Person.reset_column_information
1066
- assert Person.new.administrator?
1067
-
1068
- unless current_adapter?(:IBM_DBAdapter)
1069
- assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
1070
- else
1071
- assert_nothing_raised { Person.connection.change_column_default "people", "administrator", false }
1072
- end
1073
- Person.reset_column_information
1074
- assert !Person.new.administrator?
1075
- ensure
1076
- Person.connection.remove_column("people", "administrator") rescue nil
1077
- end
1078
-
1079
- def test_change_column_default
1080
- Person.connection.change_column_default "people", "first_name", "Tester"
1081
- Person.reset_column_information
1082
- assert_equal "Tester", Person.new.first_name
1083
- end
1084
-
1085
- def test_change_column_quotes_column_names
1086
- Person.connection.create_table :testings do |t|
1087
- unless current_adapter?(:IBM_DBAdapter)
1088
- t.column :select, :string
1089
- else
1090
- # If no limit specified by default column of length 255 is created, which later cannot be scaled down to 10
1091
- t.column :select, :string, :limit => 5
1092
- end
1093
- end
1094
-
1095
- assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
1096
-
1097
- # Oracle needs primary key value from sequence
1098
- if current_adapter?(:OracleAdapter)
1099
- assert_nothing_raised { Person.connection.execute "insert into testings (id, #{Person.connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" }
1100
- else
1101
- assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
1102
- end
1103
- ensure
1104
- Person.connection.drop_table :testings rescue nil
1105
- end
1106
-
1107
- def test_keeping_default_and_notnull_constaint_on_change
1108
- Person.connection.create_table :testings do |t|
1109
- t.column :title, :string
1110
- end
1111
- person_klass = Class.new(Person)
1112
- person_klass.table_name = 'testings'
1113
-
1114
- person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
1115
- person_klass.reset_column_information
1116
- assert_equal 99, person_klass.columns_hash["wealth"].default
1117
- assert_equal false, person_klass.columns_hash["wealth"].null
1118
- # Oracle needs primary key value from sequence
1119
- if current_adapter?(:OracleAdapter)
1120
- assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")}
1121
- else
1122
- assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
1123
- end
1124
-
1125
- # change column default to see that column doesn't lose its not null definition
1126
- person_klass.connection.change_column_default "testings", "wealth", 100
1127
- person_klass.reset_column_information
1128
- assert_equal 100, person_klass.columns_hash["wealth"].default
1129
- assert_equal false, person_klass.columns_hash["wealth"].null
1130
-
1131
- # rename column to see that column doesn't lose its not null and/or default definition
1132
- if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
1133
- person_klass.connection.rename_column "testings", "wealth", "money"
1134
- person_klass.reset_column_information
1135
- assert_nil person_klass.columns_hash["wealth"]
1136
- assert_equal 100, person_klass.columns_hash["money"].default
1137
- assert_equal false, person_klass.columns_hash["money"].null
1138
- end
1139
-
1140
- # change column
1141
- unless current_adapter?(:IBM_DBAdapter)
1142
- person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
1143
- person_klass.reset_column_information
1144
- assert_equal 1000, person_klass.columns_hash["money"].default
1145
- assert_equal false, person_klass.columns_hash["money"].null
1146
- else
1147
- person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 15, :scale => 1,:null => false, :default => 1000
1148
- person_klass.reset_column_information
1149
- assert_equal 1000, person_klass.columns_hash["wealth"].default
1150
- assert_equal false, person_klass.columns_hash["wealth"].null
1151
- end
1152
-
1153
- # change column, make it nullable and clear default
1154
- unless current_adapter?(:IBM_DBAdapter)
1155
- person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
1156
- person_klass.reset_column_information
1157
- assert_nil person_klass.columns_hash["money"].default
1158
- assert_equal true, person_klass.columns_hash["money"].null
1159
- else
1160
- person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 20, :scale => 2, :null => true, :default => nil
1161
- person_klass.reset_column_information
1162
- assert_nil person_klass.columns_hash["wealth"].default
1163
- assert_equal true, person_klass.columns_hash["wealth"].null
1164
- end
1165
-
1166
- # change_column_null, make it not nullable and set null values to a default value
1167
- unless current_adapter?(:IBM_DBAdapter)
1168
- person_klass.connection.execute('UPDATE testings SET money = NULL')
1169
- person_klass.connection.change_column_null "testings", "money", false, 2000
1170
- person_klass.reset_column_information
1171
- assert_nil person_klass.columns_hash["money"].default
1172
- assert_equal false, person_klass.columns_hash["money"].null
1173
- assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
1174
- else
1175
- # Trying to set the value of the column wealth to NULL and
1176
- # in the next statement a not null constraint is being applied which is wrong
1177
- #person_klass.connection.execute('UPDATE testings SET money = NULL')
1178
- person_klass.connection.change_column_null "testings", "wealth", false, 2000
1179
- person_klass.reset_column_information
1180
- #assert_nil person_klass.columns_hash["wealth"].default #Setting default to 2000 and expecting nil is nor correct
1181
- assert_not_nil person_klass.columns_hash["wealth"].default
1182
- assert_equal false, person_klass.columns_hash["wealth"].null
1183
- #Changing default does not change the already inserted value. Hence expecting 2000 is wrong.
1184
- assert_equal [99], Person.connection.select_values("SELECT wealth FROM testings").map { |s| s.to_i }.sort
1185
- end
1186
- ensure
1187
- Person.connection.drop_table :testings rescue nil
1188
- end
1189
-
1190
- def test_change_column_default_to_null
1191
- Person.connection.change_column_default "people", "first_name", nil
1192
- Person.reset_column_information
1193
- assert_nil Person.new.first_name
1194
- end
1195
-
1196
- def test_column_exists
1197
- Person.connection.create_table :testings do |t|
1198
- t.column :foo, :string
1199
- end
1200
-
1201
- assert Person.connection.column_exists?(:testings, :foo)
1202
- assert !Person.connection.column_exists?(:testings, :bar)
1203
- ensure
1204
- Person.connection.drop_table :testings rescue nil
1205
- end
1206
-
1207
- def test_column_exists_with_type
1208
- Person.connection.create_table :testings do |t|
1209
- t.column :foo, :string
1210
- t.column :bar, :decimal, :precision => 8, :scale => 2
1211
- end
1212
-
1213
- assert Person.connection.column_exists?(:testings, :foo, :string)
1214
- assert !Person.connection.column_exists?(:testings, :foo, :integer)
1215
- assert Person.connection.column_exists?(:testings, :bar, :decimal)
1216
- assert !Person.connection.column_exists?(:testings, :bar, :integer)
1217
- ensure
1218
- Person.connection.drop_table :testings rescue nil
1219
- end
1220
-
1221
- def test_column_exists_with_definition
1222
- Person.connection.create_table :testings do |t|
1223
- t.column :foo, :string, :limit => 100
1224
- t.column :bar, :decimal, :precision => 8, :scale => 2
1225
- end
1226
-
1227
- assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100)
1228
- assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50)
1229
- assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2)
1230
- assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2)
1231
- ensure
1232
- Person.connection.drop_table :testings rescue nil
1233
- end
1234
-
1235
- def test_column_exists_on_table_with_no_options_parameter_supplied
1236
- Person.connection.create_table :testings do |t|
1237
- t.string :foo
1238
- end
1239
- Person.connection.change_table :testings do |t|
1240
- assert t.column_exists?(:foo)
1241
- assert !(t.column_exists?(:bar))
1242
- end
1243
- ensure
1244
- Person.connection.drop_table :testings rescue nil
1245
- end
1246
-
1247
- def test_add_table
1248
- assert !Reminder.table_exists?
1249
-
1250
- WeNeedReminders.up
1251
-
1252
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1253
- assert_equal "hello world", Reminder.find(:first).content
1254
-
1255
- WeNeedReminders.down
1256
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1257
- end
1258
-
1259
- def test_add_table_with_decimals
1260
- Person.connection.drop_table :big_numbers rescue nil
1261
-
1262
- assert !BigNumber.table_exists?
1263
- GiveMeBigNumbers.up
1264
-
1265
- assert BigNumber.create(
1266
- :bank_balance => 1586.43,
1267
- :big_bank_balance => BigDecimal("1000234000567.95"),
1268
- :world_population => 6000000000,
1269
- :my_house_population => 3,
1270
- :value_of_e => BigDecimal("2.7182818284590452353602875")
1271
- )
1272
-
1273
- b = BigNumber.find(:first)
1274
- assert_not_nil b
1275
-
1276
- assert_not_nil b.bank_balance
1277
- assert_not_nil b.big_bank_balance
1278
- assert_not_nil b.world_population
1279
- assert_not_nil b.my_house_population
1280
- assert_not_nil b.value_of_e
1281
-
1282
- # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
1283
- # is_a?(Bignum)
1284
- unless current_adapter?(:IBM_DBAdapter)
1285
- assert_kind_of Integer, b.world_population
1286
- else
1287
- assert_kind_of BigDecimal, b.world_population
1288
- end
1289
- assert_equal 6000000000, b.world_population
1290
- unless current_adapter?(:IBM_DBAdapter)
1291
- assert_kind_of Fixnum, b.my_house_population
1292
- else
1293
- assert_kind_of BigDecimal, b.my_house_population
1294
- end
1295
- assert_equal 3, b.my_house_population
1296
- assert_kind_of BigDecimal, b.bank_balance
1297
- assert_equal BigDecimal("1586.43"), b.bank_balance
1298
- assert_kind_of BigDecimal, b.big_bank_balance
1299
- assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
1300
-
1301
- # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
1302
- # precision/scale explicitly left out. By the SQL standard, numbers
1303
- # assigned to this field should be truncated but that's seldom respected.
1304
- if current_adapter?(:PostgreSQLAdapter)
1305
- # - PostgreSQL changes the SQL spec on columns declared simply as
1306
- # "decimal" to something more useful: instead of being given a scale
1307
- # of 0, they take on the compile-time limit for precision and scale,
1308
- # so the following should succeed unless you have used really wacky
1309
- # compilation options
1310
- # - SQLite2 has the default behavior of preserving all data sent in,
1311
- # so this happens there too
1312
- assert_kind_of BigDecimal, b.value_of_e
1313
- assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
1314
- elsif current_adapter?(:SQLite3Adapter)
1315
- # - SQLite3 stores a float, in violation of SQL
1316
- assert_kind_of BigDecimal, b.value_of_e
1317
- assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
1318
- else
1319
- # - SQL standard is an integer
1320
- unless current_adapter?(:IBM_DBAdapter)
1321
- assert_kind_of Fixnum, b.value_of_e
1322
- else
1323
- assert_kind_of BigDecimal, b.value_of_e
1324
- end
1325
- assert_equal 2, b.value_of_e
1326
- end
1327
-
1328
- GiveMeBigNumbers.down
1329
- assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
1330
- end
1331
-
1332
- def test_migrator
1333
- assert !Person.column_methods_hash.include?(:last_name)
1334
- assert !Reminder.table_exists?
1335
-
1336
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1337
-
1338
- assert_equal 3, ActiveRecord::Migrator.current_version
1339
- Person.reset_column_information
1340
- assert Person.column_methods_hash.include?(:last_name)
1341
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1342
- assert_equal "hello world", Reminder.find(:first).content
1343
-
1344
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
1345
-
1346
- assert_equal 0, ActiveRecord::Migrator.current_version
1347
- Person.reset_column_information
1348
- assert !Person.column_methods_hash.include?(:last_name)
1349
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1350
- end
1351
-
1352
- def test_filtering_migrations
1353
- assert !Person.column_methods_hash.include?(:last_name)
1354
- assert !Reminder.table_exists?
1355
-
1356
- name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
1357
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
1358
-
1359
- Person.reset_column_information
1360
- assert Person.column_methods_hash.include?(:last_name)
1361
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1362
-
1363
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
1364
-
1365
- Person.reset_column_information
1366
- assert !Person.column_methods_hash.include?(:last_name)
1367
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1368
- end
1369
-
1370
- class MockMigration < ActiveRecord::Migration
1371
- attr_reader :went_up, :went_down
1372
- def initialize
1373
- @went_up = false
1374
- @went_down = false
1375
- end
1376
-
1377
- def up
1378
- @went_up = true
1379
- super
1380
- end
1381
-
1382
- def down
1383
- @went_down = true
1384
- super
1385
- end
1386
- end
1387
-
1388
- def test_instance_based_migration_up
1389
- migration = MockMigration.new
1390
- assert !migration.went_up, 'have not gone up'
1391
- assert !migration.went_down, 'have not gone down'
1392
-
1393
- migration.migrate :up
1394
- assert migration.went_up, 'have gone up'
1395
- assert !migration.went_down, 'have not gone down'
1396
- end
1397
-
1398
- def test_instance_based_migration_down
1399
- migration = MockMigration.new
1400
- assert !migration.went_up, 'have not gone up'
1401
- assert !migration.went_down, 'have not gone down'
1402
-
1403
- migration.migrate :down
1404
- assert !migration.went_up, 'have gone up'
1405
- assert migration.went_down, 'have not gone down'
1406
- end
1407
-
1408
- def test_migrator_one_up
1409
- assert !Person.column_methods_hash.include?(:last_name)
1410
- assert !Reminder.table_exists?
1411
-
1412
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1413
-
1414
- Person.reset_column_information
1415
- assert Person.column_methods_hash.include?(:last_name)
1416
- assert !Reminder.table_exists?
1417
-
1418
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
1419
-
1420
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1421
- assert_equal "hello world", Reminder.find(:first).content
1422
- end
1423
-
1424
- def test_migrator_one_down
1425
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1426
-
1427
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
1428
-
1429
- Person.reset_column_information
1430
- assert Person.column_methods_hash.include?(:last_name)
1431
- assert !Reminder.table_exists?
1432
- end
1433
-
1434
- def test_migrator_one_up_one_down
1435
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1436
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1437
-
1438
- assert !Person.column_methods_hash.include?(:last_name)
1439
- assert !Reminder.table_exists?
1440
- end
1441
-
1442
- def test_migrator_double_up
1443
- assert_equal(0, ActiveRecord::Migrator.current_version)
1444
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1445
- assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
1446
- assert_equal(1, ActiveRecord::Migrator.current_version)
1447
- end
1448
-
1449
- def test_migrator_double_down
1450
- assert_equal(0, ActiveRecord::Migrator.current_version)
1451
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1452
- ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
1453
- assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
1454
- assert_equal(0, ActiveRecord::Migrator.current_version)
1455
- end
1456
-
1457
- if ActiveRecord::Base.connection.supports_ddl_transactions?
1458
- def test_migrator_one_up_with_exception_and_rollback
1459
- assert !Person.column_methods_hash.include?(:last_name)
1460
-
1461
- e = assert_raise(StandardError) do
1462
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
1463
- end
1464
-
1465
- assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
1466
-
1467
- Person.reset_column_information
1468
- assert !Person.column_methods_hash.include?(:last_name)
1469
- end
1470
- end
1471
-
1472
- def test_finds_migrations
1473
- migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
1474
-
1475
- [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1476
- assert_equal migrations[i].version, pair.first
1477
- assert_equal migrations[i].name, pair.last
1478
- end
1479
- end
1480
-
1481
- def test_finds_migrations_in_subdirectories
1482
- migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations
1483
-
1484
- [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1485
- assert_equal migrations[i].version, pair.first
1486
- assert_equal migrations[i].name, pair.last
1487
- end
1488
- end
1489
-
1490
- def test_finds_migrations_from_two_directories
1491
- directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps']
1492
- migrations = ActiveRecord::Migrator.new(:up, directories).migrations
1493
-
1494
- [[20090101010101, "PeopleHaveHobbies"],
1495
- [20090101010202, "PeopleHaveDescriptions"],
1496
- [20100101010101, "ValidWithTimestampsPeopleHaveLastNames"],
1497
- [20100201010101, "ValidWithTimestampsWeNeedReminders"],
1498
- [20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i|
1499
- assert_equal pair.first, migrations[i].version
1500
- assert_equal pair.last, migrations[i].name
1501
- end
1502
- end
1503
-
1504
- def test_dump_schema_information_outputs_lexically_ordered_versions
1505
- migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps'
1506
- ActiveRecord::Migrator.run(:up, migration_path, 20100301010101)
1507
- ActiveRecord::Migrator.run(:up, migration_path, 20100201010101)
1508
-
1509
- schema_info = ActiveRecord::Base.connection.dump_schema_information
1510
- assert_match(/20100201010101.*20100301010101/m, schema_info)
1511
- end
1512
-
1513
- def test_finds_pending_migrations
1514
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
1515
- migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
1516
-
1517
- assert_equal 1, migrations.size
1518
- assert_equal migrations[0].version, 3
1519
- assert_equal migrations[0].name, 'InterleavedInnocentJointable'
1520
- end
1521
-
1522
- def test_relative_migrations
1523
- list = Dir.chdir(MIGRATIONS_ROOT) do
1524
- ActiveRecord::Migrator.up("valid/", 1)
1525
- end
1526
-
1527
- migration_proxy = list.find { |item|
1528
- item.name == 'ValidPeopleHaveLastNames'
1529
- }
1530
- assert migration_proxy, 'should find pending migration'
1531
- end
1532
-
1533
- def test_only_loads_pending_migrations
1534
- # migrate up to 1
1535
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1536
-
1537
- proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
1538
-
1539
- names = proxies.map(&:name)
1540
- assert !names.include?('ValidPeopleHaveLastNames')
1541
- assert names.include?('WeNeedReminders')
1542
- assert names.include?('InnocentJointable')
1543
- end
1544
-
1545
- def test_target_version_zero_should_run_only_once
1546
- # migrate up to 1
1547
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1548
-
1549
- # migrate down to 0
1550
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1551
-
1552
- # migrate down to 0 again
1553
- proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1554
- assert_equal [], proxies
1555
- end
1556
-
1557
- def test_migrator_db_has_no_schema_migrations_table
1558
- # Oracle adapter raises error if semicolon is present as last character
1559
- if current_adapter?(:OracleAdapter)
1560
- ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
1561
- else
1562
- ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
1563
- end
1564
- assert_nothing_raised do
1565
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1566
- end
1567
- end
1568
-
1569
- def test_migrator_verbosity
1570
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1571
- assert_not_equal 0, ActiveRecord::Migration.message_count
1572
- ActiveRecord::Migration.message_count = 0
1573
-
1574
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1575
- assert_not_equal 0, ActiveRecord::Migration.message_count
1576
- ActiveRecord::Migration.message_count = 0
1577
- end
1578
-
1579
- def test_migrator_verbosity_off
1580
- ActiveRecord::Migration.verbose = false
1581
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1582
- assert_equal 0, ActiveRecord::Migration.message_count
1583
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1584
- assert_equal 0, ActiveRecord::Migration.message_count
1585
- end
1586
-
1587
- def test_migrator_going_down_due_to_version_target
1588
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1589
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1590
-
1591
- assert !Person.column_methods_hash.include?(:last_name)
1592
- assert !Reminder.table_exists?
1593
-
1594
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1595
-
1596
- Person.reset_column_information
1597
- assert Person.column_methods_hash.include?(:last_name)
1598
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1599
- assert_equal "hello world", Reminder.find(:first).content
1600
- end
1601
-
1602
- def test_migrator_rollback
1603
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1604
- assert_equal(3, ActiveRecord::Migrator.current_version)
1605
-
1606
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1607
- assert_equal(2, ActiveRecord::Migrator.current_version)
1608
-
1609
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1610
- assert_equal(1, ActiveRecord::Migrator.current_version)
1611
-
1612
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1613
- assert_equal(0, ActiveRecord::Migrator.current_version)
1614
-
1615
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1616
- assert_equal(0, ActiveRecord::Migrator.current_version)
1617
- end
1618
-
1619
- def test_migrator_forward
1620
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1621
- assert_equal(1, ActiveRecord::Migrator.current_version)
1622
-
1623
- ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2)
1624
- assert_equal(3, ActiveRecord::Migrator.current_version)
1625
-
1626
- ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid")
1627
- assert_equal(3, ActiveRecord::Migrator.current_version)
1628
- end
1629
-
1630
- def test_get_all_versions
1631
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1632
- assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions)
1633
-
1634
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1635
- assert_equal([1,2], ActiveRecord::Migrator.get_all_versions)
1636
-
1637
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1638
- assert_equal([1], ActiveRecord::Migrator.get_all_versions)
1639
-
1640
- ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1641
- assert_equal([], ActiveRecord::Migrator.get_all_versions)
1642
- end
1643
-
1644
- def test_schema_migrations_table_name
1645
- ActiveRecord::Base.table_name_prefix = "prefix_"
1646
- ActiveRecord::Base.table_name_suffix = "_suffix"
1647
- Reminder.reset_table_name
1648
- assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
1649
- ActiveRecord::Base.table_name_prefix = ""
1650
- ActiveRecord::Base.table_name_suffix = ""
1651
- Reminder.reset_table_name
1652
- assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
1653
- ensure
1654
- ActiveRecord::Base.table_name_prefix = ""
1655
- ActiveRecord::Base.table_name_suffix = ""
1656
- end
1657
-
1658
- def test_proper_table_name
1659
- assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
1660
- assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
1661
- assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
1662
- Reminder.reset_table_name
1663
- assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
1664
-
1665
- # Use the model's own prefix/suffix if a model is given
1666
- ActiveRecord::Base.table_name_prefix = "ARprefix_"
1667
- ActiveRecord::Base.table_name_suffix = "_ARsuffix"
1668
- Reminder.table_name_prefix = 'prefix_'
1669
- Reminder.table_name_suffix = '_suffix'
1670
- Reminder.reset_table_name
1671
- assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
1672
- Reminder.table_name_prefix = ''
1673
- Reminder.table_name_suffix = ''
1674
- Reminder.reset_table_name
1675
-
1676
- # Use AR::Base's prefix/suffix if string or symbol is given
1677
- ActiveRecord::Base.table_name_prefix = "prefix_"
1678
- ActiveRecord::Base.table_name_suffix = "_suffix"
1679
- Reminder.reset_table_name
1680
- assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
1681
- assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
1682
- ActiveRecord::Base.table_name_prefix = ""
1683
- ActiveRecord::Base.table_name_suffix = ""
1684
- Reminder.reset_table_name
1685
- end
1686
-
1687
- def test_rename_table_with_prefix_and_suffix
1688
- assert !Thing.table_exists?
1689
- ActiveRecord::Base.table_name_prefix = 'prefix_'
1690
- ActiveRecord::Base.table_name_suffix = '_suffix'
1691
- Thing.reset_table_name
1692
- Thing.reset_sequence_name
1693
- WeNeedThings.up
1694
-
1695
- assert Thing.create("content" => "hello world")
1696
- assert_equal "hello world", Thing.find(:first).content
1697
-
1698
- RenameThings.up
1699
- Thing.table_name = "prefix_awesome_things_suffix"
1700
-
1701
- assert_equal "hello world", Thing.find(:first).content
1702
- ensure
1703
- ActiveRecord::Base.table_name_prefix = ''
1704
- ActiveRecord::Base.table_name_suffix = ''
1705
- Thing.reset_table_name
1706
- Thing.reset_sequence_name
1707
- end
1708
-
1709
- def test_add_drop_table_with_prefix_and_suffix
1710
- assert !Reminder.table_exists?
1711
- ActiveRecord::Base.table_name_prefix = 'prefix_'
1712
- ActiveRecord::Base.table_name_suffix = '_suffix'
1713
- Reminder.reset_table_name
1714
- Reminder.reset_sequence_name
1715
- WeNeedReminders.up
1716
- assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1717
- assert_equal "hello world", Reminder.find(:first).content
1718
-
1719
- WeNeedReminders.down
1720
- assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1721
- ensure
1722
- ActiveRecord::Base.table_name_prefix = ''
1723
- ActiveRecord::Base.table_name_suffix = ''
1724
- Reminder.reset_table_name
1725
- Reminder.reset_sequence_name
1726
- end
1727
-
1728
- def test_create_table_with_binary_column
1729
- Person.connection.drop_table :binary_testings rescue nil
1730
-
1731
- assert_nothing_raised {
1732
- Person.connection.create_table :binary_testings do |t|
1733
- t.column "data", :binary, :null => false
1734
- end
1735
- }
1736
-
1737
- columns = Person.connection.columns(:binary_testings)
1738
- data_column = columns.detect { |c| c.name == "data" }
1739
-
1740
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
1741
- assert_equal '', data_column.default
1742
- else
1743
- assert_nil data_column.default
1744
- end
1745
-
1746
- Person.connection.drop_table :binary_testings rescue nil
1747
- end
1748
-
1749
- def test_migrator_with_duplicates
1750
- assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
1751
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
1752
- end
1753
- end
1754
-
1755
- def test_migrator_with_duplicate_names
1756
- assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
1757
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
1758
- end
1759
- end
1760
-
1761
- def test_migrator_with_missing_version_numbers
1762
- assert_raise(ActiveRecord::UnknownMigrationVersionError) do
1763
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
1764
- end
1765
- end
1766
-
1767
- def test_create_table_with_custom_sequence_name
1768
- return unless current_adapter? :OracleAdapter
1769
-
1770
- # table name is 29 chars, the standard sequence name will
1771
- # be 33 chars and should be shortened
1772
- assert_nothing_raised do
1773
- begin
1774
- Person.connection.create_table :table_with_name_thats_just_ok do |t|
1775
- t.column :foo, :string, :null => false
1776
- end
1777
- ensure
1778
- Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
1779
- end
1780
- end
1781
-
1782
- # should be all good w/ a custom sequence name
1783
- assert_nothing_raised do
1784
- begin
1785
- Person.connection.create_table :table_with_name_thats_just_ok,
1786
- :sequence_name => 'suitably_short_seq' do |t|
1787
- t.column :foo, :string, :null => false
1788
- end
1789
-
1790
- Person.connection.execute("select suitably_short_seq.nextval from dual")
1791
-
1792
- ensure
1793
- Person.connection.drop_table :table_with_name_thats_just_ok,
1794
- :sequence_name => 'suitably_short_seq' rescue nil
1795
- end
1796
- end
1797
-
1798
- # confirm the custom sequence got dropped
1799
- assert_raise(ActiveRecord::StatementInvalid) do
1800
- Person.connection.execute("select suitably_short_seq.nextval from dual")
1801
- end
1802
- end
1803
-
1804
- protected
1805
- def with_env_tz(new_tz = 'US/Eastern')
1806
- old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1807
- yield
1808
- ensure
1809
- old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1810
- end
1811
-
1812
- end
1813
-
1814
- class MigrationLoggerTest < ActiveRecord::TestCase
1815
- def test_migration_should_be_run_without_logger
1816
- previous_logger = ActiveRecord::Base.logger
1817
- ActiveRecord::Base.logger = nil
1818
- assert_nothing_raised do
1819
- ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1820
- end
1821
- ensure
1822
- ActiveRecord::Base.logger = previous_logger
1823
- end
1824
- end
1825
-
1826
- class InterleavedMigrationsTest < ActiveRecord::TestCase
1827
- def test_migrator_interleaved_migrations
1828
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
1829
-
1830
- assert_nothing_raised do
1831
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
1832
- end
1833
-
1834
- Person.reset_column_information
1835
- assert Person.column_methods_hash.include?(:last_name)
1836
-
1837
- assert_nothing_raised do
1838
- proxies = ActiveRecord::Migrator.down(
1839
- MIGRATIONS_ROOT + "/interleaved/pass_3")
1840
- names = proxies.map(&:name)
1841
- assert names.include?('InterleavedPeopleHaveLastNames')
1842
- assert names.include?('InterleavedInnocentJointable')
1843
- end
1844
- end
1845
- end
1846
-
1847
- class ReservedWordsMigrationTest < ActiveRecord::TestCase
1848
- def test_drop_index_from_table_named_values
1849
- connection = Person.connection
1850
- connection.create_table :values, :force => true do |t|
1851
- t.integer :value
1852
- end
1853
-
1854
- assert_nothing_raised do
1855
- connection.add_index :values, :value
1856
- connection.remove_index :values, :column => :value
1857
- end
1858
-
1859
- connection.drop_table :values rescue nil
1860
- end
1861
- end
1862
-
1863
-
1864
- class ChangeTableMigrationsTest < ActiveRecord::TestCase
1865
- def setup
1866
- @connection = Person.connection
1867
- @connection.create_table :delete_me, :force => true do |t|
1868
- end
1869
- end
1870
-
1871
- def teardown
1872
- Person.connection.drop_table :delete_me rescue nil
1873
- end
1874
-
1875
- def test_references_column_type_adds_id
1876
- with_change_table do |t|
1877
- @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1878
- t.references :customer
1879
- end
1880
- end
1881
-
1882
- def test_remove_references_column_type_removes_id
1883
- with_change_table do |t|
1884
- @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1885
- t.remove_references :customer
1886
- end
1887
- end
1888
-
1889
- def test_add_belongs_to_works_like_add_references
1890
- with_change_table do |t|
1891
- @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1892
- t.belongs_to :customer
1893
- end
1894
- end
1895
-
1896
- def test_remove_belongs_to_works_like_remove_references
1897
- with_change_table do |t|
1898
- @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1899
- t.remove_belongs_to :customer
1900
- end
1901
- end
1902
-
1903
- def test_references_column_type_with_polymorphic_adds_type
1904
- with_change_table do |t|
1905
- @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1906
- @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1907
- t.references :taggable, :polymorphic => true
1908
- end
1909
- end
1910
-
1911
- def test_remove_references_column_type_with_polymorphic_removes_type
1912
- with_change_table do |t|
1913
- @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1914
- @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1915
- t.remove_references :taggable, :polymorphic => true
1916
- end
1917
- end
1918
-
1919
- def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1920
- with_change_table do |t|
1921
- @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1922
- @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1923
- t.references :taggable, :polymorphic => true, :null => false
1924
- end
1925
- end
1926
-
1927
- def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1928
- with_change_table do |t|
1929
- @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1930
- @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1931
- t.remove_references :taggable, :polymorphic => true, :null => false
1932
- end
1933
- end
1934
-
1935
- def test_timestamps_creates_updated_at_and_created_at
1936
- with_change_table do |t|
1937
- @connection.expects(:add_timestamps).with(:delete_me)
1938
- t.timestamps
1939
- end
1940
- end
1941
-
1942
- def test_remove_timestamps_creates_updated_at_and_created_at
1943
- with_change_table do |t|
1944
- @connection.expects(:remove_timestamps).with(:delete_me)
1945
- t.remove_timestamps
1946
- end
1947
- end
1948
-
1949
- def string_column
1950
- if current_adapter?(:PostgreSQLAdapter)
1951
- "character varying(255)"
1952
- elsif current_adapter?(:OracleAdapter)
1953
- 'VARCHAR2(255)'
1954
- else
1955
- 'varchar(255)'
1956
- end
1957
- end
1958
-
1959
- def integer_column
1960
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
1961
- 'int(11)'
1962
- elsif current_adapter?(:OracleAdapter)
1963
- 'NUMBER(38)'
1964
- else
1965
- 'integer'
1966
- end
1967
- end
1968
-
1969
- def test_integer_creates_integer_column
1970
- with_change_table do |t|
1971
- @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
1972
- @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
1973
- t.integer :foo, :bar
1974
- end
1975
- end
1976
-
1977
- def test_string_creates_string_column
1978
- with_change_table do |t|
1979
- @connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
1980
- @connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
1981
- t.string :foo, :bar
1982
- end
1983
- end
1984
-
1985
- def test_column_creates_column
1986
- with_change_table do |t|
1987
- @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1988
- t.column :bar, :integer
1989
- end
1990
- end
1991
-
1992
- def test_column_creates_column_with_options
1993
- with_change_table do |t|
1994
- @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1995
- t.column :bar, :integer, :null => false
1996
- end
1997
- end
1998
-
1999
- def test_index_creates_index
2000
- with_change_table do |t|
2001
- @connection.expects(:add_index).with(:delete_me, :bar, {})
2002
- t.index :bar
2003
- end
2004
- end
2005
-
2006
- def test_index_creates_index_with_options
2007
- with_change_table do |t|
2008
- @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
2009
- t.index :bar, :unique => true
2010
- end
2011
- end
2012
-
2013
- def test_index_exists
2014
- with_change_table do |t|
2015
- @connection.expects(:index_exists?).with(:delete_me, :bar, {})
2016
- t.index_exists?(:bar)
2017
- end
2018
- end
2019
-
2020
- def test_index_exists_with_options
2021
- with_change_table do |t|
2022
- @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true})
2023
- t.index_exists?(:bar, :unique => true)
2024
- end
2025
- end
2026
-
2027
- def test_change_changes_column
2028
- with_change_table do |t|
2029
- @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
2030
- t.change :bar, :string
2031
- end
2032
- end
2033
-
2034
- def test_change_changes_column_with_options
2035
- with_change_table do |t|
2036
- @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
2037
- t.change :bar, :string, :null => true
2038
- end
2039
- end
2040
-
2041
- def test_change_default_changes_column
2042
- with_change_table do |t|
2043
- @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
2044
- t.change_default :bar, :string
2045
- end
2046
- end
2047
-
2048
- def test_remove_drops_single_column
2049
- with_change_table do |t|
2050
- @connection.expects(:remove_column).with(:delete_me, [:bar])
2051
- t.remove :bar
2052
- end
2053
- end
2054
-
2055
- def test_remove_drops_multiple_columns
2056
- with_change_table do |t|
2057
- @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
2058
- t.remove :bar, :baz
2059
- end
2060
- end
2061
-
2062
- def test_remove_index_removes_index_with_options
2063
- with_change_table do |t|
2064
- @connection.expects(:remove_index).with(:delete_me, {:unique => true})
2065
- t.remove_index :unique => true
2066
- end
2067
- end
2068
-
2069
- def test_rename_renames_column
2070
- with_change_table do |t|
2071
- @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
2072
- t.rename :bar, :baz
2073
- end
2074
- end
2075
-
2076
- protected
2077
- def with_change_table
2078
- Person.connection.change_table :delete_me do |t|
2079
- yield t
2080
- end
2081
- end
2082
- end
2083
-
2084
- if ActiveRecord::Base.connection.supports_bulk_alter?
2085
- class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
2086
- def setup
2087
- @connection = Person.connection
2088
- @connection.create_table(:delete_me, :force => true) {|t| }
2089
- end
2090
-
2091
- def teardown
2092
- Person.connection.drop_table(:delete_me) rescue nil
2093
- end
2094
-
2095
- def test_adding_multiple_columns
2096
- assert_queries(1) do
2097
- with_bulk_change_table do |t|
2098
- t.column :name, :string
2099
- t.string :qualification, :experience
2100
- t.integer :age, :default => 0
2101
- t.date :birthdate
2102
- t.timestamps
2103
- end
2104
- end
2105
-
2106
- assert_equal 8, columns.size
2107
- [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
2108
- assert_equal 0, column(:age).default
2109
- end
2110
-
2111
- def test_removing_columns
2112
- with_bulk_change_table do |t|
2113
- t.string :qualification, :experience
2114
- end
2115
-
2116
- [:qualification, :experience].each {|c| assert column(c) }
2117
-
2118
- assert_queries(1) do
2119
- with_bulk_change_table do |t|
2120
- t.remove :qualification, :experience
2121
- t.string :qualification_experience
2122
- end
2123
- end
2124
-
2125
- [:qualification, :experience].each {|c| assert ! column(c) }
2126
- assert column(:qualification_experience)
2127
- end
2128
-
2129
- def test_adding_indexes
2130
- with_bulk_change_table do |t|
2131
- t.string :username
2132
- t.string :name
2133
- t.integer :age
2134
- end
2135
-
2136
- # Adding an index fires a query every time to check if an index already exists or not
2137
- assert_queries(3) do
2138
- with_bulk_change_table do |t|
2139
- t.index :username, :unique => true, :name => :awesome_username_index
2140
- t.index [:name, :age]
2141
- end
2142
- end
2143
-
2144
- assert_equal 2, indexes.size
2145
-
2146
- name_age_index = index(:index_delete_me_on_name_and_age)
2147
- assert_equal ['name', 'age'].sort, name_age_index.columns.sort
2148
- assert ! name_age_index.unique
2149
-
2150
- assert index(:awesome_username_index).unique
2151
- end
2152
-
2153
- def test_removing_index
2154
- with_bulk_change_table do |t|
2155
- t.string :name
2156
- t.index :name
2157
- end
2158
-
2159
- assert index(:index_delete_me_on_name)
2160
-
2161
- assert_queries(3) do
2162
- with_bulk_change_table do |t|
2163
- t.remove_index :name
2164
- t.index :name, :name => :new_name_index, :unique => true
2165
- end
2166
- end
2167
-
2168
- assert ! index(:index_delete_me_on_name)
2169
-
2170
- new_name_index = index(:new_name_index)
2171
- assert new_name_index.unique
2172
- end
2173
-
2174
- def test_changing_columns
2175
- with_bulk_change_table do |t|
2176
- t.string :name
2177
- t.date :birthdate
2178
- end
2179
-
2180
- assert ! column(:name).default
2181
- assert_equal :date, column(:birthdate).type
2182
-
2183
- # One query for columns (delete_me table)
2184
- # One query for primary key (delete_me table)
2185
- # One query to do the bulk change
2186
- assert_queries(3) do
2187
- with_bulk_change_table do |t|
2188
- t.change :name, :string, :default => 'NONAME'
2189
- t.change :birthdate, :datetime
2190
- end
2191
- end
2192
-
2193
- assert_equal 'NONAME', column(:name).default
2194
- assert_equal :datetime, column(:birthdate).type
2195
- end
2196
-
2197
- protected
2198
-
2199
- def with_bulk_change_table
2200
- # Reset columns/indexes cache as we're changing the table
2201
- @columns = @indexes = nil
2202
-
2203
- Person.connection.change_table(:delete_me, :bulk => true) do |t|
2204
- yield t
2205
- end
2206
- end
2207
-
2208
- def column(name)
2209
- columns.detect {|c| c.name == name.to_s }
2210
- end
2211
-
2212
- def columns
2213
- @columns ||= Person.connection.columns('delete_me')
2214
- end
2215
-
2216
- def index(name)
2217
- indexes.detect {|i| i.name == name.to_s }
2218
- end
2219
-
2220
- def indexes
2221
- @indexes ||= Person.connection.indexes('delete_me')
2222
- end
2223
- end # AlterTableMigrationsTest
2224
-
2225
- end
2226
-
2227
- class CopyMigrationsTest < ActiveRecord::TestCase
2228
- def setup
2229
- end
2230
-
2231
- def clear
2232
- ActiveRecord::Base.timestamped_migrations = true
2233
- to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
2234
- File.delete(*to_delete)
2235
- end
2236
-
2237
- def test_copying_migrations_without_timestamps
2238
- ActiveRecord::Base.timestamped_migrations = false
2239
- @migrations_path = MIGRATIONS_ROOT + "/valid"
2240
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2241
-
2242
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
2243
- assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
2244
- assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
2245
- assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
2246
-
2247
- expected = "# This migration comes from bukkits (originally 1)"
2248
- assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
2249
-
2250
- files_count = Dir[@migrations_path + "/*.rb"].length
2251
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
2252
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2253
- assert copied.empty?
2254
- ensure
2255
- clear
2256
- end
2257
-
2258
- def test_copying_migrations_without_timestamps_from_2_sources
2259
- ActiveRecord::Base.timestamped_migrations = false
2260
- @migrations_path = MIGRATIONS_ROOT + "/valid"
2261
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2262
-
2263
- sources = ActiveSupport::OrderedHash.new
2264
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
2265
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
2266
- ActiveRecord::Migration.copy(@migrations_path, sources)
2267
- assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
2268
- assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
2269
- assert File.exists?(@migrations_path + "/6_create_articles.omg.rb")
2270
- assert File.exists?(@migrations_path + "/7_create_comments.omg.rb")
2271
-
2272
- files_count = Dir[@migrations_path + "/*.rb"].length
2273
- ActiveRecord::Migration.copy(@migrations_path, sources)
2274
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2275
- ensure
2276
- clear
2277
- end
2278
-
2279
- def test_copying_migrations_with_timestamps
2280
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2281
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2282
-
2283
- Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2284
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2285
- assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2286
- assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2287
- expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
2288
- @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
2289
- assert_equal expected, copied.map(&:filename)
2290
-
2291
- files_count = Dir[@migrations_path + "/*.rb"].length
2292
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2293
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2294
- assert copied.empty?
2295
- end
2296
- ensure
2297
- clear
2298
- end
2299
-
2300
- def test_copying_migrations_with_timestamps_from_2_sources
2301
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2302
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2303
-
2304
- sources = ActiveSupport::OrderedHash.new
2305
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2306
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
2307
-
2308
- Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2309
- copied = ActiveRecord::Migration.copy(@migrations_path, sources)
2310
- assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2311
- assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2312
- assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb")
2313
- assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb")
2314
- assert_equal 4, copied.length
2315
-
2316
- files_count = Dir[@migrations_path + "/*.rb"].length
2317
- ActiveRecord::Migration.copy(@migrations_path, sources)
2318
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2319
- end
2320
- ensure
2321
- clear
2322
- end
2323
-
2324
- def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
2325
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2326
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2327
-
2328
- Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
2329
- ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2330
- assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
2331
- assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
2332
-
2333
- files_count = Dir[@migrations_path + "/*.rb"].length
2334
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2335
- assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2336
- assert copied.empty?
2337
- end
2338
- ensure
2339
- clear
2340
- end
2341
-
2342
- def test_skipping_migrations
2343
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2344
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2345
-
2346
- sources = ActiveSupport::OrderedHash.new
2347
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2348
- sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
2349
-
2350
- skipped = []
2351
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
2352
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2353
- assert_equal 2, copied.length
2354
-
2355
- assert_equal 1, skipped.length
2356
- assert_equal ["omg PeopleHaveHobbies"], skipped
2357
- ensure
2358
- clear
2359
- end
2360
-
2361
- def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
2362
- @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2363
- @existing_migrations = Dir[@migrations_path + "/*.rb"]
2364
-
2365
- sources = ActiveSupport::OrderedHash.new
2366
- sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2367
-
2368
- skipped = []
2369
- on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
2370
- copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2371
- ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2372
-
2373
- assert_equal 2, copied.length
2374
- assert_equal 0, skipped.length
2375
- ensure
2376
- clear
2377
- end
2378
-
2379
- def test_copying_migrations_to_non_existing_directory
2380
- @migrations_path = MIGRATIONS_ROOT + "/non_existing"
2381
- @existing_migrations = []
2382
-
2383
- Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2384
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2385
- assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2386
- assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2387
- assert_equal 2, copied.length
2388
- end
2389
- ensure
2390
- clear
2391
- Dir.delete(@migrations_path)
2392
- end
2393
-
2394
- def test_copying_migrations_to_empty_directory
2395
- @migrations_path = MIGRATIONS_ROOT + "/empty"
2396
- @existing_migrations = []
2397
-
2398
- Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2399
- copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2400
- assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2401
- assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2402
- assert_equal 2, copied.length
2403
- end
2404
- ensure
2405
- clear
2406
- end
2407
- end
2408
- end
1
+ require "cases/helper"
2
+ require 'bigdecimal/util'
3
+
4
+ require 'models/person'
5
+ require 'models/topic'
6
+ require 'models/developer'
7
+
8
+ require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
9
+ require MIGRATIONS_ROOT + "/rename/1_we_need_things"
10
+ require MIGRATIONS_ROOT + "/rename/2_rename_things"
11
+ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
12
+
13
+ if ActiveRecord::Base.connection.supports_migrations?
14
+ class BigNumber < ActiveRecord::Base; end
15
+
16
+ class Reminder < ActiveRecord::Base; end
17
+
18
+ class Thing < ActiveRecord::Base; end
19
+
20
+ class ActiveRecord::Migration
21
+ class << self
22
+ attr_accessor :message_count
23
+ end
24
+
25
+ def puts(text="")
26
+ ActiveRecord::Migration.message_count ||= 0
27
+ ActiveRecord::Migration.message_count += 1
28
+ end
29
+ end
30
+
31
+ class MigrationTableAndIndexTest < ActiveRecord::TestCase
32
+ def test_add_schema_info_respects_prefix_and_suffix
33
+ conn = ActiveRecord::Base.connection
34
+
35
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
36
+ # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
37
+ ActiveRecord::Base.table_name_prefix = 'p_'
38
+ ActiveRecord::Base.table_name_suffix = '_s'
39
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
40
+
41
+ conn.initialize_schema_migrations_table
42
+
43
+ assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
44
+ ensure
45
+ ActiveRecord::Base.table_name_prefix = ""
46
+ ActiveRecord::Base.table_name_suffix = ""
47
+ end
48
+ end
49
+
50
+ class MigrationTest < ActiveRecord::TestCase
51
+ self.use_transactional_fixtures = false
52
+
53
+ if (current_adapter?(:IBM_DBAdapter))
54
+ #Rename is supported only for server zOS 9 , DB2 COBRA and Informix
55
+ server_type = ActiveRecord::Base.connection.servertype.class.name
56
+ @ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
57
+ server_type.class.name.include?('::IBM_IDS') ||
58
+ (server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
59
+ end
60
+
61
+ fixtures :people
62
+
63
+ def setup
64
+ ActiveRecord::Migration.verbose = true
65
+ ActiveRecord::Migration.message_count = 0
66
+ end
67
+
68
+ def teardown
69
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
70
+ ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
71
+
72
+ %w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table|
73
+ Thing.connection.drop_table(table) rescue nil
74
+ end
75
+ Thing.reset_column_information
76
+
77
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
78
+ Reminder.connection.drop_table(table) rescue nil
79
+ end
80
+ Reminder.reset_column_information
81
+
82
+ %w(last_name key bio age height wealth birthday favorite_day
83
+ moment_of_truth male administrator funny).each do |column|
84
+ Person.connection.remove_column('people', column) rescue nil
85
+ end
86
+ Person.connection.remove_column("people", "first_name") rescue nil
87
+ Person.connection.remove_column("people", "middle_name") rescue nil
88
+ Person.connection.add_column("people", "first_name", :string, :limit => 40)
89
+ Person.reset_column_information
90
+ end
91
+
92
+ def test_add_index
93
+ # Limit size of last_name and key columns to support Firebird index limitations
94
+ Person.connection.add_column "people", "last_name", :string, :limit => 100
95
+ Person.connection.add_column "people", "key", :string, :limit => 100
96
+ Person.connection.add_column "people", "administrator", :boolean
97
+
98
+ assert_nothing_raised { Person.connection.add_index("people", "last_name") }
99
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
100
+
101
+ # Orcl nds shrt indx nms. Sybs 2.
102
+ # OpenBase does not have named indexes. You must specify a single column name
103
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
104
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
105
+ assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
106
+ # Oracle adapter cannot have specified index name larger than 30 characters
107
+ # Oracle adapter is shortening index name when just column list is given
108
+ unless current_adapter?(:OracleAdapter)
109
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
110
+ assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) }
111
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
112
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
113
+ end
114
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
115
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
116
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
117
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
118
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) }
119
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
120
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) }
121
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
122
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) }
123
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
124
+ end
125
+
126
+ # quoting
127
+ # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
128
+ # OpenBase does not have named indexes. You must specify a single column name
129
+ unless current_adapter?(:OpenBaseAdapter)
130
+ unless current_adapter?(:IBM_DBAdapter)
131
+ Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
132
+ else
133
+ Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'first_name'}"
134
+ end
135
+ assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
136
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
137
+ end
138
+
139
+ # Sybase adapter does not support indexes on :boolean columns
140
+ # OpenBase does not have named indexes. You must specify a single column
141
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
142
+ assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
143
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
144
+ end
145
+
146
+ # Selected adapters support index sort order
147
+ if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
148
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) }
149
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
150
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) }
151
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
152
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) }
153
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
154
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) }
155
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
156
+ end
157
+ end
158
+
159
+ def test_index_symbol_names
160
+ assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name }
161
+ assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
162
+ assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name }
163
+ assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name)
164
+ end
165
+
166
+ def test_add_index_length_limit
167
+ good_index_name = 'x' * Person.connection.index_name_length
168
+ too_long_index_name = good_index_name + 'x'
169
+ assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) }
170
+ assert !Person.connection.index_name_exists?("people", too_long_index_name, false)
171
+ assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) }
172
+ assert Person.connection.index_name_exists?("people", good_index_name, false)
173
+ Person.connection.remove_index("people", :name => good_index_name)
174
+ end
175
+
176
+ def test_add_index_attribute_length_limit
177
+ Person.connection.add_index :people, [:first_name, :primary_contact_id], :length => {:first_name => 10, :primary_contact_id => nil}, :name => "attribute_length"
178
+ assert Person.connection.index_exists?(:people, [:first_name, :primary_contact_id], :name => "attribute_length")
179
+ ensure
180
+ Person.connection.remove_index(:people, :name => "attribute_length")
181
+ end
182
+
183
+ def test_remove_nonexistent_index
184
+ # we do this by name, so OpenBase is a wash as noted above
185
+ unless current_adapter?(:OpenBaseAdapter)
186
+ assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") }
187
+ end
188
+ end
189
+
190
+ def test_rename_index
191
+ unless current_adapter?(:OpenBaseAdapter)
192
+ # keep the names short to make Oracle and similar behave
193
+ Person.connection.add_index('people', [:first_name], :name => 'old_idx')
194
+ assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') }
195
+ # if the adapter doesn't support the indexes call, pick defaults that let the test pass
196
+ assert !Person.connection.index_name_exists?('people', 'old_idx', false)
197
+ assert Person.connection.index_name_exists?('people', 'new_idx', true)
198
+ end
199
+ end
200
+
201
+ def test_double_add_index
202
+ unless current_adapter?(:OpenBaseAdapter)
203
+ Person.connection.add_index('people', [:first_name], :name => 'some_idx')
204
+ assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') }
205
+ end
206
+ end
207
+
208
+ def test_index_exists
209
+ Person.connection.create_table :testings do |t|
210
+ t.column :foo, :string, :limit => 100
211
+ t.column :bar, :string, :limit => 100
212
+ end
213
+ Person.connection.add_index :testings, :foo
214
+
215
+ assert Person.connection.index_exists?(:testings, :foo)
216
+ assert !Person.connection.index_exists?(:testings, :bar)
217
+ ensure
218
+ Person.connection.drop_table :testings rescue nil
219
+ end
220
+
221
+ def test_index_exists_on_multiple_columns
222
+ Person.connection.create_table :testings do |t|
223
+ t.column :foo, :string, :limit => 100
224
+ t.column :bar, :string, :limit => 100
225
+ end
226
+ Person.connection.add_index :testings, [:foo, :bar]
227
+
228
+ assert Person.connection.index_exists?(:testings, [:foo, :bar])
229
+ ensure
230
+ Person.connection.drop_table :testings rescue nil
231
+ end
232
+
233
+ def test_unique_index_exists
234
+ Person.connection.create_table :testings do |t|
235
+ t.column :foo, :string, :limit => 100
236
+ end
237
+ Person.connection.add_index :testings, :foo, :unique => true
238
+
239
+ assert Person.connection.index_exists?(:testings, :foo, :unique => true)
240
+ ensure
241
+ Person.connection.drop_table :testings rescue nil
242
+ end
243
+
244
+ def test_named_index_exists
245
+ Person.connection.create_table :testings do |t|
246
+ t.column :foo, :string, :limit => 100
247
+ end
248
+ Person.connection.add_index :testings, :foo, :name => "custom_index_name"
249
+
250
+ assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name")
251
+ ensure
252
+ Person.connection.drop_table :testings rescue nil
253
+ end
254
+
255
+ def testing_table_with_only_foo_attribute
256
+ Person.connection.create_table :testings, :id => false do |t|
257
+ t.column :foo, :string
258
+ end
259
+
260
+ yield Person.connection
261
+ ensure
262
+ Person.connection.drop_table :testings rescue nil
263
+ end
264
+ protected :testing_table_with_only_foo_attribute
265
+
266
+ def test_create_table_without_id
267
+ testing_table_with_only_foo_attribute do |connection|
268
+ assert_equal connection.columns(:testings).size, 1
269
+ end
270
+ end
271
+
272
+ unless current_adapter?(:IBM_DBAdapter)
273
+ # For DB2: Cannot add a primary key to a table with some rows already in it as it violates the unique constraint
274
+ # Secondly GENERATED BY DEFAULT AS IDENTITY cannot be applied in a alter table command.
275
+ # as this will be wrong sql syntax for DB
276
+ def test_add_column_with_primary_key_attribute
277
+ testing_table_with_only_foo_attribute do |connection|
278
+ assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
279
+ assert_equal connection.columns(:testings).size, 2
280
+ end
281
+ end
282
+ end
283
+
284
+ def test_create_table_adds_id
285
+ Person.connection.create_table :testings do |t|
286
+ t.column :foo, :string
287
+ end
288
+
289
+ assert_equal %w(foo id),
290
+ Person.connection.columns(:testings).map { |c| c.name }.sort
291
+ ensure
292
+ Person.connection.drop_table :testings rescue nil
293
+ end
294
+
295
+ def test_create_table_with_not_null_column
296
+ assert_nothing_raised do
297
+ Person.connection.create_table :testings do |t|
298
+ t.column :foo, :string, :null => false
299
+ end
300
+ end
301
+
302
+ assert_raise(ActiveRecord::StatementInvalid) do
303
+ Person.connection.execute "insert into testings (foo) values (NULL)"
304
+ end
305
+ ensure
306
+ Person.connection.drop_table :testings rescue nil
307
+ end
308
+
309
+ def test_create_table_with_defaults
310
+ # MySQL doesn't allow defaults on TEXT or BLOB columns.
311
+ mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
312
+
313
+ Person.connection.create_table :testings do |t|
314
+ t.column :one, :string, :default => "hello"
315
+ t.column :two, :boolean, :default => true
316
+ t.column :three, :boolean, :default => false
317
+ t.column :four, :integer, :default => 1
318
+ t.column :five, :text, :default => "hello" unless mysql
319
+ end
320
+
321
+ columns = Person.connection.columns(:testings)
322
+ one = columns.detect { |c| c.name == "one" }
323
+ two = columns.detect { |c| c.name == "two" }
324
+ three = columns.detect { |c| c.name == "three" }
325
+ four = columns.detect { |c| c.name == "four" }
326
+ five = columns.detect { |c| c.name == "five" } unless mysql
327
+
328
+ assert_equal "hello", one.default
329
+ assert_equal true, two.default
330
+ assert_equal false, three.default
331
+ assert_equal 1, four.default
332
+ assert_equal "hello", five.default unless mysql
333
+
334
+ ensure
335
+ Person.connection.drop_table :testings rescue nil
336
+ end
337
+
338
+ def test_create_table_with_limits
339
+ assert_nothing_raised do
340
+ Person.connection.create_table :testings do |t|
341
+ t.column :foo, :string, :limit => 255
342
+
343
+ t.column :default_int, :integer
344
+
345
+ t.column :one_int, :integer, :limit => 1
346
+ t.column :four_int, :integer, :limit => 4
347
+ t.column :eight_int, :integer, :limit => 8
348
+ t.column :eleven_int, :integer, :limit => 11
349
+ end
350
+ end
351
+
352
+ columns = Person.connection.columns(:testings)
353
+ foo = columns.detect { |c| c.name == "foo" }
354
+ assert_equal 255, foo.limit
355
+
356
+ default = columns.detect { |c| c.name == "default_int" }
357
+ one = columns.detect { |c| c.name == "one_int" }
358
+ four = columns.detect { |c| c.name == "four_int" }
359
+ eight = columns.detect { |c| c.name == "eight_int" }
360
+ eleven = columns.detect { |c| c.name == "eleven_int" }
361
+
362
+ if current_adapter?(:PostgreSQLAdapter)
363
+ assert_equal 'integer', default.sql_type
364
+ assert_equal 'smallint', one.sql_type
365
+ assert_equal 'integer', four.sql_type
366
+ assert_equal 'bigint', eight.sql_type
367
+ assert_equal 'integer', eleven.sql_type
368
+ elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
369
+ assert_match 'int(11)', default.sql_type
370
+ assert_match 'tinyint', one.sql_type
371
+ assert_match 'int', four.sql_type
372
+ assert_match 'bigint', eight.sql_type
373
+ assert_match 'int(11)', eleven.sql_type
374
+ elsif current_adapter?(:OracleAdapter)
375
+ assert_equal 'NUMBER(38)', default.sql_type
376
+ assert_equal 'NUMBER(1)', one.sql_type
377
+ assert_equal 'NUMBER(4)', four.sql_type
378
+ assert_equal 'NUMBER(8)', eight.sql_type
379
+ end
380
+ ensure
381
+ Person.connection.drop_table :testings rescue nil
382
+ end
383
+
384
+ def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
385
+ ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
386
+
387
+ Person.connection.create_table :testings do |t|
388
+ t.column :foo, :string
389
+ end
390
+
391
+ assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
392
+ ensure
393
+ Person.connection.drop_table :testings rescue nil
394
+ ActiveRecord::Base.primary_key_prefix_type = nil
395
+ end
396
+
397
+ def test_create_table_with_primary_key_prefix_as_table_name
398
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
399
+
400
+ Person.connection.create_table :testings do |t|
401
+ t.column :foo, :string
402
+ end
403
+
404
+ assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
405
+ ensure
406
+ Person.connection.drop_table :testings rescue nil
407
+ ActiveRecord::Base.primary_key_prefix_type = nil
408
+ end
409
+
410
+ def test_create_table_with_force_true_does_not_drop_nonexisting_table
411
+ if Person.connection.table_exists?(:testings2)
412
+ Person.connection.drop_table :testings2
413
+ end
414
+
415
+ # using a copy as we need the drop_table method to
416
+ # continue to work for the ensure block of the test
417
+ temp_conn = Person.connection.dup
418
+ temp_conn.expects(:drop_table).never
419
+ temp_conn.create_table :testings2, :force => true do |t|
420
+ t.column :foo, :string
421
+ end
422
+ ensure
423
+ Person.connection.drop_table :testings2 rescue nil
424
+ end
425
+
426
+ def test_create_table_with_timestamps_should_create_datetime_columns
427
+ table_name = :testings
428
+
429
+ Person.connection.create_table table_name do |t|
430
+ t.timestamps
431
+ end
432
+ created_columns = Person.connection.columns(table_name)
433
+
434
+ created_at_column = created_columns.detect {|c| c.name == 'created_at' }
435
+ updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
436
+
437
+ assert !created_at_column.null
438
+ assert !updated_at_column.null
439
+ ensure
440
+ Person.connection.drop_table table_name rescue nil
441
+ end
442
+
443
+ def test_create_table_with_timestamps_should_create_datetime_columns_with_options
444
+ table_name = :testings
445
+
446
+ Person.connection.create_table table_name do |t|
447
+ t.timestamps :null => false
448
+ end
449
+ created_columns = Person.connection.columns(table_name)
450
+
451
+ created_at_column = created_columns.detect {|c| c.name == 'created_at' }
452
+ updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
453
+
454
+ assert !created_at_column.null
455
+ assert !updated_at_column.null
456
+ ensure
457
+ Person.connection.drop_table table_name rescue nil
458
+ end
459
+
460
+ def test_create_table_without_a_block
461
+ table_name = :testings
462
+ Person.connection.create_table table_name
463
+ ensure
464
+ Person.connection.drop_table table_name rescue nil
465
+ end
466
+
467
+ # Sybase, and SQLite3 will not allow you to add a NOT NULL
468
+ # column to a table without a default value.
469
+ unless current_adapter?(:SybaseAdapter, :SQLite3Adapter, :IBM_DBAdapter)
470
+ def test_add_column_not_null_without_default
471
+ Person.connection.create_table :testings do |t|
472
+ t.column :foo, :string
473
+ end
474
+ Person.connection.add_column :testings, :bar, :string, :null => false
475
+
476
+ assert_raise(ActiveRecord::StatementInvalid) do
477
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
478
+ end
479
+ ensure
480
+ Person.connection.drop_table :testings rescue nil
481
+ end
482
+ end
483
+
484
+ def test_add_column_not_null_with_default
485
+ Person.connection.create_table :testings do |t|
486
+ t.column :foo, :string
487
+ end
488
+
489
+ con = Person.connection
490
+ Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
491
+ Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
492
+ Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
493
+ assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
494
+
495
+ assert_raise(ActiveRecord::StatementInvalid) do
496
+ unless current_adapter?(:OpenBaseAdapter)
497
+ Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
498
+ else
499
+ Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)",
500
+ "Testing Insert","id",2)
501
+ end
502
+ end
503
+ ensure
504
+ Person.connection.drop_table :testings rescue nil
505
+ end
506
+
507
+ # We specifically do a manual INSERT here, and then test only the SELECT
508
+ # functionality. This allows us to more easily catch INSERT being broken,
509
+ # but SELECT actually working fine.
510
+ def test_native_decimal_insert_manual_vs_automatic
511
+ correct_value = '0012345678901234567890.0123456789'.to_d
512
+
513
+ Person.delete_all
514
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
515
+ Person.reset_column_information
516
+
517
+ # Do a manual insertion
518
+ if current_adapter?(:OracleAdapter)
519
+ Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
520
+ elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
521
+ Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
522
+ elsif current_adapter?(:PostgreSQLAdapter)
523
+ Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
524
+ elsif current_adapter?(:IBM_DBAdapter)
525
+ Person.connection.execute "insert into people (wealth, created_at, updated_at, lock_version, first_name) values (12345678901234567890.0123456789, CURRENT TIMESTAMP, CURRENT TIMESTAMP, 0, 'Jim')"
526
+ else
527
+ Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
528
+ end
529
+
530
+ # SELECT
531
+ row = Person.find(:first)
532
+ assert_kind_of BigDecimal, row.wealth
533
+
534
+ # If this assert fails, that means the SELECT is broken!
535
+ unless current_adapter?(:SQLite3Adapter)
536
+ assert_equal correct_value, row.wealth
537
+ end
538
+
539
+ # Reset to old state
540
+ Person.delete_all
541
+
542
+ # Now use the Rails insertion
543
+ unless current_adapter?(:IBM_DBAdapter)
544
+ assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
545
+ else
546
+ # First_name is a not null column, hence ensure a value is specified
547
+ assert_nothing_raised { Person.create ({:wealth => BigDecimal.new("12345678901234567890.0123456789"), :first_name => "James"}) }
548
+ end
549
+
550
+ # SELECT
551
+ row = Person.find(:first)
552
+ assert_kind_of BigDecimal, row.wealth
553
+
554
+ # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
555
+ unless current_adapter?(:SQLite3Adapter)
556
+ assert_equal correct_value, row.wealth
557
+ end
558
+
559
+ # Reset to old state
560
+ Person.connection.del_column "people", "wealth" rescue nil
561
+ Person.reset_column_information
562
+ end
563
+
564
+ def test_add_column_with_precision_and_scale
565
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
566
+ Person.reset_column_information
567
+
568
+ wealth_column = Person.columns_hash['wealth']
569
+ assert_equal 9, wealth_column.precision
570
+ assert_equal 7, wealth_column.scale
571
+ end
572
+
573
+ # Test SQLite adapter specifically for decimal types with precision and scale
574
+ # attributes, since these need to be maintained in schema but aren't actually
575
+ # used in SQLite itself
576
+ if current_adapter?(:SQLite3Adapter)
577
+ def test_change_column_with_new_precision_and_scale
578
+ Person.delete_all
579
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
580
+ Person.reset_column_information
581
+
582
+ Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8
583
+ Person.reset_column_information
584
+
585
+ wealth_column = Person.columns_hash['wealth']
586
+ assert_equal 12, wealth_column.precision
587
+ assert_equal 8, wealth_column.scale
588
+ end
589
+
590
+ def test_change_column_preserve_other_column_precision_and_scale
591
+ Person.delete_all
592
+ Person.connection.add_column 'people', 'last_name', :string
593
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
594
+ Person.reset_column_information
595
+
596
+ wealth_column = Person.columns_hash['wealth']
597
+ assert_equal 9, wealth_column.precision
598
+ assert_equal 7, wealth_column.scale
599
+
600
+ Person.connection.change_column 'people', 'last_name', :string, :null => false
601
+ Person.reset_column_information
602
+
603
+ wealth_column = Person.columns_hash['wealth']
604
+ assert_equal 9, wealth_column.precision
605
+ assert_equal 7, wealth_column.scale
606
+ end
607
+ end
608
+
609
+ def test_native_types
610
+ Person.delete_all
611
+ Person.connection.add_column "people", "last_name", :string
612
+ Person.connection.add_column "people", "bio", :text
613
+ Person.connection.add_column "people", "age", :integer
614
+ Person.connection.add_column "people", "height", :float
615
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
616
+ Person.connection.add_column "people", "birthday", :datetime
617
+ Person.connection.add_column "people", "favorite_day", :date
618
+ Person.connection.add_column "people", "moment_of_truth", :datetime
619
+ Person.connection.add_column "people", "male", :boolean
620
+ Person.reset_column_information
621
+
622
+ assert_nothing_raised do
623
+ Person.create :first_name => 'bob', :last_name => 'bobsen',
624
+ :bio => "I was born ....", :age => 18, :height => 1.78,
625
+ :wealth => BigDecimal.new("12345678901234567890.0123456789"),
626
+ :birthday => 18.years.ago, :favorite_day => 10.days.ago,
627
+ :moment_of_truth => "1782-10-10 21:40:18", :male => true
628
+ end
629
+
630
+ bob = Person.find(:first)
631
+ assert_equal 'bob', bob.first_name
632
+ assert_equal 'bobsen', bob.last_name
633
+ assert_equal "I was born ....", bob.bio
634
+ assert_equal 18, bob.age
635
+
636
+ # Test for 30 significant digits (beyond the 16 of float), 10 of them
637
+ # after the decimal place.
638
+
639
+ unless current_adapter?(:SQLite3Adapter)
640
+ assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
641
+ end
642
+
643
+ assert_equal true, bob.male?
644
+
645
+ assert_equal String, bob.first_name.class
646
+ assert_equal String, bob.last_name.class
647
+ assert_equal String, bob.bio.class
648
+ assert_equal Fixnum, bob.age.class
649
+ assert_equal Time, bob.birthday.class
650
+
651
+ if current_adapter?(:OracleAdapter, :SybaseAdapter)
652
+ # Sybase, and Oracle don't differentiate between date/time
653
+ assert_equal Time, bob.favorite_day.class
654
+ else
655
+ assert_equal Date, bob.favorite_day.class
656
+ end
657
+
658
+ # Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column
659
+ # therefore no timezone change is done afterwards when default timezone is changed
660
+ unless current_adapter?(:OracleAdapter)
661
+ # Test DateTime column and defaults, including timezone.
662
+ # FIXME: moment of truth may be Time on 64-bit platforms.
663
+ if bob.moment_of_truth.is_a?(DateTime)
664
+
665
+ with_env_tz 'US/Eastern' do
666
+ bob.reload
667
+ assert_equal DateTime.local_offset, bob.moment_of_truth.offset
668
+ assert_not_equal 0, bob.moment_of_truth.offset
669
+ assert_not_equal "Z", bob.moment_of_truth.zone
670
+ # US/Eastern is -5 hours from GMT
671
+ assert_equal Rational(-5, 24), bob.moment_of_truth.offset
672
+ assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM
673
+ assert_equal DateTime::ITALY, bob.moment_of_truth.start
674
+ end
675
+ end
676
+ end
677
+
678
+ assert_instance_of TrueClass, bob.male?
679
+ assert_kind_of BigDecimal, bob.wealth
680
+ end
681
+
682
+ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
683
+ def test_unabstracted_database_dependent_types
684
+ Person.delete_all
685
+
686
+ ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
687
+ Person.reset_column_information
688
+ assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type)
689
+ ensure
690
+ ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
691
+ end
692
+ end
693
+
694
+ def test_add_remove_single_field_using_string_arguments
695
+ assert !Person.column_methods_hash.include?(:last_name)
696
+
697
+ ActiveRecord::Migration.add_column 'people', 'last_name', :string
698
+
699
+ Person.reset_column_information
700
+ assert Person.column_methods_hash.include?(:last_name)
701
+
702
+ ActiveRecord::Migration.remove_column 'people', 'last_name'
703
+
704
+ Person.reset_column_information
705
+ assert !Person.column_methods_hash.include?(:last_name)
706
+ end
707
+
708
+ def test_add_remove_single_field_using_symbol_arguments
709
+ assert !Person.column_methods_hash.include?(:last_name)
710
+
711
+ ActiveRecord::Migration.add_column :people, :last_name, :string
712
+
713
+ Person.reset_column_information
714
+ assert Person.column_methods_hash.include?(:last_name)
715
+
716
+ ActiveRecord::Migration.remove_column :people, :last_name
717
+
718
+ Person.reset_column_information
719
+ assert !Person.column_methods_hash.include?(:last_name)
720
+ end
721
+
722
+ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
723
+ def testing_table_for_positioning
724
+ Person.connection.create_table :testings, :id => false do |t|
725
+ t.column :first, :integer
726
+ t.column :second, :integer
727
+ t.column :third, :integer
728
+ end
729
+
730
+ yield Person.connection
731
+ ensure
732
+ Person.connection.drop_table :testings rescue nil
733
+ end
734
+ protected :testing_table_for_positioning
735
+
736
+ def test_column_positioning
737
+ testing_table_for_positioning do |conn|
738
+ assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
739
+ end
740
+ end
741
+
742
+ def test_add_column_with_positioning
743
+ testing_table_for_positioning do |conn|
744
+ conn.add_column :testings, :new_col, :integer
745
+ assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
746
+ end
747
+ testing_table_for_positioning do |conn|
748
+ conn.add_column :testings, :new_col, :integer, :first => true
749
+ assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
750
+ end
751
+ testing_table_for_positioning do |conn|
752
+ conn.add_column :testings, :new_col, :integer, :after => :first
753
+ assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
754
+ end
755
+ end
756
+
757
+ def test_change_column_with_positioning
758
+ testing_table_for_positioning do |conn|
759
+ conn.change_column :testings, :second, :integer, :first => true
760
+ assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
761
+ end
762
+ testing_table_for_positioning do |conn|
763
+ conn.change_column :testings, :second, :integer, :after => :third
764
+ assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
765
+ end
766
+ end
767
+ end
768
+
769
+ if(!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
770
+ def test_add_rename
771
+ Person.delete_all
772
+
773
+ begin
774
+ Person.connection.add_column "people", "girlfriend", :string
775
+ Person.reset_column_information
776
+ Person.create :girlfriend => 'bobette'
777
+
778
+ Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
779
+
780
+ Person.reset_column_information
781
+ bob = Person.find(:first)
782
+
783
+ assert_equal "bobette", bob.exgirlfriend
784
+ ensure
785
+ Person.connection.remove_column("people", "girlfriend") rescue nil
786
+ Person.connection.remove_column("people", "exgirlfriend") rescue nil
787
+ end
788
+
789
+ end
790
+
791
+ def test_rename_column_using_symbol_arguments
792
+ begin
793
+ names_before = Person.find(:all).map(&:first_name)
794
+ Person.connection.rename_column :people, :first_name, :nick_name
795
+ Person.reset_column_information
796
+ assert Person.column_names.include?("nick_name")
797
+ assert_equal names_before, Person.find(:all).map(&:nick_name)
798
+ ensure
799
+ Person.connection.remove_column("people","nick_name")
800
+ Person.connection.add_column("people","first_name", :string)
801
+ end
802
+ end
803
+
804
+ def test_rename_column
805
+ begin
806
+ names_before = Person.find(:all).map(&:first_name)
807
+ Person.connection.rename_column "people", "first_name", "nick_name"
808
+ Person.reset_column_information
809
+ assert Person.column_names.include?("nick_name")
810
+ assert_equal names_before, Person.find(:all).map(&:nick_name)
811
+ ensure
812
+ Person.connection.remove_column("people","nick_name")
813
+ Person.connection.add_column("people","first_name", :string)
814
+ end
815
+ end
816
+
817
+ def test_rename_column_preserves_default_value_not_null
818
+ begin
819
+ default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
820
+ assert_equal 70000, default_before
821
+ Developer.connection.rename_column "developers", "salary", "anual_salary"
822
+ Developer.reset_column_information
823
+ assert Developer.column_names.include?("anual_salary")
824
+ default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
825
+ assert_equal 70000, default_after
826
+ ensure
827
+ Developer.connection.rename_column "developers", "anual_salary", "salary"
828
+ Developer.reset_column_information
829
+ end
830
+ end
831
+
832
+ def test_rename_nonexistent_column
833
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
834
+ table.column :hat_name, :string, :default => nil
835
+ end
836
+ exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
837
+ ActiveRecord::StatementInvalid
838
+ else
839
+ ActiveRecord::ActiveRecordError
840
+ end
841
+ assert_raise(exception) do
842
+ Person.connection.rename_column "hats", "nonexistent", "should_fail"
843
+ end
844
+ ensure
845
+ ActiveRecord::Base.connection.drop_table(:hats)
846
+ end
847
+
848
+ def test_rename_column_with_sql_reserved_word
849
+ begin
850
+ assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
851
+ Person.reset_column_information
852
+ assert Person.column_names.include?("group")
853
+ ensure
854
+ Person.connection.remove_column("people", "group") rescue nil
855
+ Person.connection.add_column("people", "first_name", :string) rescue nil
856
+ end
857
+ end
858
+ end
859
+
860
+ unless current_adapter?(:IBM_DBAdapter)
861
+ def test_rename_column_with_an_index
862
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
863
+ table.column :hat_name, :string, :limit => 100
864
+ table.column :hat_size, :integer
865
+ end
866
+ Person.connection.add_index :hats, :hat_name
867
+ assert_nothing_raised do
868
+ Person.connection.rename_column "hats", "hat_name", "name"
869
+ end
870
+ ensure
871
+ ActiveRecord::Base.connection.drop_table(:hats)
872
+ end
873
+ end
874
+
875
+ def test_remove_column_with_index
876
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
877
+ table.column :hat_name, :string, :limit => 100
878
+ table.column :hat_size, :integer
879
+ end
880
+ ActiveRecord::Base.connection.add_index "hats", "hat_size"
881
+
882
+ assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
883
+ ensure
884
+ ActiveRecord::Base.connection.drop_table(:hats)
885
+ end
886
+
887
+ def test_remove_column_with_multi_column_index
888
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
889
+ table.column :hat_name, :string, :limit => 100
890
+ table.column :hat_size, :integer
891
+ table.column :hat_style, :string, :limit => 100
892
+ end
893
+ ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
894
+
895
+ assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
896
+ ensure
897
+ ActiveRecord::Base.connection.drop_table(:hats)
898
+ end
899
+
900
+ def test_remove_column_no_second_parameter_raises_exception
901
+ assert_raise(ArgumentError) { Person.connection.remove_column("funny") }
902
+ end
903
+
904
+ def test_change_type_of_not_null_column
905
+ assert_nothing_raised do
906
+ unless current_adapter?(:IBM_DBAdapter)
907
+ Topic.connection.change_column "topics", "written_on", :datetime, :null => false
908
+ else
909
+ Topic.connection.change_column_null "topics", "written_on", false
910
+ end
911
+ Topic.reset_column_information
912
+
913
+ unless current_adapter?(:IBM_DBAdapter)
914
+ Topic.connection.change_column "topics", "written_on", :datetime, :null => false
915
+ else
916
+ Topic.connection.change_column_null "topics", "written_on", false
917
+ end
918
+ Topic.reset_column_information
919
+
920
+ unless current_adapter?(:IBM_DBAdapter)
921
+ Topic.connection.change_column "topics", "written_on", :datetime, :null => true
922
+ else
923
+ Topic.connection.change_column_null "topics", "written_on", true
924
+ end
925
+
926
+ Topic.reset_column_information
927
+ end
928
+ end
929
+
930
+ if current_adapter?(:SQLite3Adapter)
931
+ def test_rename_table_for_sqlite_should_work_with_reserved_words
932
+ begin
933
+ assert_nothing_raised do
934
+ ActiveRecord::Base.connection.rename_table :references, :old_references
935
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
936
+ t.column :url, :string
937
+ end
938
+ end
939
+
940
+ assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references }
941
+
942
+ # Using explicit id in insert for compatibility across all databases
943
+ con = ActiveRecord::Base.connection
944
+ assert_nothing_raised do
945
+ con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')"
946
+ end
947
+ assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1")
948
+
949
+ ensure
950
+ ActiveRecord::Base.connection.drop_table :references
951
+ ActiveRecord::Base.connection.rename_table :old_references, :references
952
+ end
953
+ end
954
+ end
955
+
956
+ def test_rename_table
957
+ begin
958
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
959
+ t.column :url, :string
960
+ end
961
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
962
+
963
+ # Using explicit id in insert for compatibility across all databases
964
+ con = ActiveRecord::Base.connection
965
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
966
+ assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
967
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
968
+
969
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
970
+
971
+ ensure
972
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
973
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
974
+ end
975
+ end
976
+
977
+ def test_change_column_nullability
978
+ Person.delete_all
979
+ Person.connection.add_column "people", "funny", :boolean
980
+ Person.reset_column_information
981
+ assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
982
+ unless current_adapter?(:IBM_DBAdapter)
983
+ Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
984
+ else
985
+ Person.connection.change_column_null "people", "funny",false
986
+ end
987
+ Person.reset_column_information
988
+ assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
989
+ unless current_adapter?(:IBM_DBAdapter)
990
+ Person.connection.change_column "people", "funny", :boolean, :null => true
991
+ else
992
+ Person.connection.change_column_null "people", "funny",true
993
+ end
994
+ Person.reset_column_information
995
+ assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
996
+ end
997
+
998
+ def test_rename_table_with_an_index
999
+ begin
1000
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
1001
+ t.column :url, :string
1002
+ end
1003
+ ActiveRecord::Base.connection.add_index :octopuses, :url
1004
+
1005
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
1006
+
1007
+ # Using explicit id in insert for compatibility across all databases
1008
+ con = ActiveRecord::Base.connection
1009
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
1010
+ assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
1011
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
1012
+
1013
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
1014
+ assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
1015
+ ensure
1016
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
1017
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
1018
+ end
1019
+ end
1020
+
1021
+ unless current_adapter?(:IBM_DBAdapter)
1022
+ # Cannot convert from type integer to varchar.
1023
+ # Safe to not run this test as add_column will be covered in other test cases
1024
+ def test_change_column
1025
+ Person.connection.add_column 'people', 'age', :integer
1026
+ label = "test_change_column Columns"
1027
+ old_columns = Person.connection.columns(Person.table_name, label)
1028
+ assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
1029
+
1030
+ assert_nothing_raised { Person.connection.change_column "people", "age", :string }
1031
+
1032
+ new_columns = Person.connection.columns(Person.table_name, label)
1033
+ assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
1034
+ assert new_columns.find { |c| c.name == 'age' and c.type == :string }
1035
+
1036
+ old_columns = Topic.connection.columns(Topic.table_name, label)
1037
+ assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
1038
+ assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
1039
+ new_columns = Topic.connection.columns(Topic.table_name, label)
1040
+ assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
1041
+ assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
1042
+ assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
1043
+ end
1044
+ end
1045
+
1046
+ def test_change_column_with_nil_default
1047
+ Person.connection.add_column "people", "contributor", :boolean, :default => true
1048
+ Person.reset_column_information
1049
+ assert Person.new.contributor?
1050
+
1051
+ unless current_adapter?(:IBM_DBAdapter)
1052
+ assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
1053
+ else
1054
+ assert_nothing_raised { Person.connection.change_column_default "people", "contributor", nil }
1055
+ end
1056
+ Person.reset_column_information
1057
+ assert !Person.new.contributor?
1058
+ assert_nil Person.new.contributor
1059
+ ensure
1060
+ Person.connection.remove_column("people", "contributor") rescue nil
1061
+ end
1062
+
1063
+ def test_change_column_with_new_default
1064
+ Person.connection.add_column "people", "administrator", :boolean, :default => true
1065
+ Person.reset_column_information
1066
+ assert Person.new.administrator?
1067
+
1068
+ unless current_adapter?(:IBM_DBAdapter)
1069
+ assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
1070
+ else
1071
+ assert_nothing_raised { Person.connection.change_column_default "people", "administrator", false }
1072
+ end
1073
+ Person.reset_column_information
1074
+ assert !Person.new.administrator?
1075
+ ensure
1076
+ Person.connection.remove_column("people", "administrator") rescue nil
1077
+ end
1078
+
1079
+ def test_change_column_default
1080
+ Person.connection.change_column_default "people", "first_name", "Tester"
1081
+ Person.reset_column_information
1082
+ assert_equal "Tester", Person.new.first_name
1083
+ end
1084
+
1085
+ def test_change_column_quotes_column_names
1086
+ Person.connection.create_table :testings do |t|
1087
+ unless current_adapter?(:IBM_DBAdapter)
1088
+ t.column :select, :string
1089
+ else
1090
+ # If no limit specified by default column of length 255 is created, which later cannot be scaled down to 10
1091
+ t.column :select, :string, :limit => 5
1092
+ end
1093
+ end
1094
+
1095
+ assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
1096
+
1097
+ # Oracle needs primary key value from sequence
1098
+ if current_adapter?(:OracleAdapter)
1099
+ assert_nothing_raised { Person.connection.execute "insert into testings (id, #{Person.connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" }
1100
+ else
1101
+ assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
1102
+ end
1103
+ ensure
1104
+ Person.connection.drop_table :testings rescue nil
1105
+ end
1106
+
1107
+ def test_keeping_default_and_notnull_constaint_on_change
1108
+ Person.connection.create_table :testings do |t|
1109
+ t.column :title, :string
1110
+ end
1111
+ person_klass = Class.new(Person)
1112
+ person_klass.table_name = 'testings'
1113
+
1114
+ person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
1115
+ person_klass.reset_column_information
1116
+ assert_equal 99, person_klass.columns_hash["wealth"].default
1117
+ assert_equal false, person_klass.columns_hash["wealth"].null
1118
+ # Oracle needs primary key value from sequence
1119
+ if current_adapter?(:OracleAdapter)
1120
+ assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")}
1121
+ else
1122
+ assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
1123
+ end
1124
+
1125
+ # change column default to see that column doesn't lose its not null definition
1126
+ person_klass.connection.change_column_default "testings", "wealth", 100
1127
+ person_klass.reset_column_information
1128
+ assert_equal 100, person_klass.columns_hash["wealth"].default
1129
+ assert_equal false, person_klass.columns_hash["wealth"].null
1130
+
1131
+ # rename column to see that column doesn't lose its not null and/or default definition
1132
+ if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
1133
+ person_klass.connection.rename_column "testings", "wealth", "money"
1134
+ person_klass.reset_column_information
1135
+ assert_nil person_klass.columns_hash["wealth"]
1136
+ assert_equal 100, person_klass.columns_hash["money"].default
1137
+ assert_equal false, person_klass.columns_hash["money"].null
1138
+ end
1139
+
1140
+ # change column
1141
+ unless current_adapter?(:IBM_DBAdapter)
1142
+ person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
1143
+ person_klass.reset_column_information
1144
+ assert_equal 1000, person_klass.columns_hash["money"].default
1145
+ assert_equal false, person_klass.columns_hash["money"].null
1146
+ else
1147
+ person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 15, :scale => 1,:null => false, :default => 1000
1148
+ person_klass.reset_column_information
1149
+ assert_equal 1000, person_klass.columns_hash["wealth"].default
1150
+ assert_equal false, person_klass.columns_hash["wealth"].null
1151
+ end
1152
+
1153
+ # change column, make it nullable and clear default
1154
+ unless current_adapter?(:IBM_DBAdapter)
1155
+ person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
1156
+ person_klass.reset_column_information
1157
+ assert_nil person_klass.columns_hash["money"].default
1158
+ assert_equal true, person_klass.columns_hash["money"].null
1159
+ else
1160
+ person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 20, :scale => 2, :null => true, :default => nil
1161
+ person_klass.reset_column_information
1162
+ assert_nil person_klass.columns_hash["wealth"].default
1163
+ assert_equal true, person_klass.columns_hash["wealth"].null
1164
+ end
1165
+
1166
+ # change_column_null, make it not nullable and set null values to a default value
1167
+ unless current_adapter?(:IBM_DBAdapter)
1168
+ person_klass.connection.execute('UPDATE testings SET money = NULL')
1169
+ person_klass.connection.change_column_null "testings", "money", false, 2000
1170
+ person_klass.reset_column_information
1171
+ assert_nil person_klass.columns_hash["money"].default
1172
+ assert_equal false, person_klass.columns_hash["money"].null
1173
+ assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
1174
+ else
1175
+ # Trying to set the value of the column wealth to NULL and
1176
+ # in the next statement a not null constraint is being applied which is wrong
1177
+ #person_klass.connection.execute('UPDATE testings SET money = NULL')
1178
+ person_klass.connection.change_column_null "testings", "wealth", false, 2000
1179
+ person_klass.reset_column_information
1180
+ #assert_nil person_klass.columns_hash["wealth"].default #Setting default to 2000 and expecting nil is nor correct
1181
+ assert_not_nil person_klass.columns_hash["wealth"].default
1182
+ assert_equal false, person_klass.columns_hash["wealth"].null
1183
+ #Changing default does not change the already inserted value. Hence expecting 2000 is wrong.
1184
+ assert_equal [99], Person.connection.select_values("SELECT wealth FROM testings").map { |s| s.to_i }.sort
1185
+ end
1186
+ ensure
1187
+ Person.connection.drop_table :testings rescue nil
1188
+ end
1189
+
1190
+ def test_change_column_default_to_null
1191
+ Person.connection.change_column_default "people", "first_name", nil
1192
+ Person.reset_column_information
1193
+ assert_nil Person.new.first_name
1194
+ end
1195
+
1196
+ def test_column_exists
1197
+ Person.connection.create_table :testings do |t|
1198
+ t.column :foo, :string
1199
+ end
1200
+
1201
+ assert Person.connection.column_exists?(:testings, :foo)
1202
+ assert !Person.connection.column_exists?(:testings, :bar)
1203
+ ensure
1204
+ Person.connection.drop_table :testings rescue nil
1205
+ end
1206
+
1207
+ def test_column_exists_with_type
1208
+ Person.connection.create_table :testings do |t|
1209
+ t.column :foo, :string
1210
+ t.column :bar, :decimal, :precision => 8, :scale => 2
1211
+ end
1212
+
1213
+ assert Person.connection.column_exists?(:testings, :foo, :string)
1214
+ assert !Person.connection.column_exists?(:testings, :foo, :integer)
1215
+ assert Person.connection.column_exists?(:testings, :bar, :decimal)
1216
+ assert !Person.connection.column_exists?(:testings, :bar, :integer)
1217
+ ensure
1218
+ Person.connection.drop_table :testings rescue nil
1219
+ end
1220
+
1221
+ def test_column_exists_with_definition
1222
+ Person.connection.create_table :testings do |t|
1223
+ t.column :foo, :string, :limit => 100
1224
+ t.column :bar, :decimal, :precision => 8, :scale => 2
1225
+ end
1226
+
1227
+ assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100)
1228
+ assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50)
1229
+ assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2)
1230
+ assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2)
1231
+ ensure
1232
+ Person.connection.drop_table :testings rescue nil
1233
+ end
1234
+
1235
+ def test_column_exists_on_table_with_no_options_parameter_supplied
1236
+ Person.connection.create_table :testings do |t|
1237
+ t.string :foo
1238
+ end
1239
+ Person.connection.change_table :testings do |t|
1240
+ assert t.column_exists?(:foo)
1241
+ assert !(t.column_exists?(:bar))
1242
+ end
1243
+ ensure
1244
+ Person.connection.drop_table :testings rescue nil
1245
+ end
1246
+
1247
+ def test_add_table
1248
+ assert !Reminder.table_exists?
1249
+
1250
+ WeNeedReminders.up
1251
+
1252
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1253
+ assert_equal "hello world", Reminder.find(:first).content
1254
+
1255
+ WeNeedReminders.down
1256
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1257
+ end
1258
+
1259
+ def test_add_table_with_decimals
1260
+ Person.connection.drop_table :big_numbers rescue nil
1261
+
1262
+ assert !BigNumber.table_exists?
1263
+ GiveMeBigNumbers.up
1264
+
1265
+ assert BigNumber.create(
1266
+ :bank_balance => 1586.43,
1267
+ :big_bank_balance => BigDecimal("1000234000567.95"),
1268
+ :world_population => 6000000000,
1269
+ :my_house_population => 3,
1270
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
1271
+ )
1272
+
1273
+ b = BigNumber.find(:first)
1274
+ assert_not_nil b
1275
+
1276
+ assert_not_nil b.bank_balance
1277
+ assert_not_nil b.big_bank_balance
1278
+ assert_not_nil b.world_population
1279
+ assert_not_nil b.my_house_population
1280
+ assert_not_nil b.value_of_e
1281
+
1282
+ # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
1283
+ # is_a?(Bignum)
1284
+ unless current_adapter?(:IBM_DBAdapter)
1285
+ assert_kind_of Integer, b.world_population
1286
+ else
1287
+ assert_kind_of BigDecimal, b.world_population
1288
+ end
1289
+ assert_equal 6000000000, b.world_population
1290
+ unless current_adapter?(:IBM_DBAdapter)
1291
+ assert_kind_of Fixnum, b.my_house_population
1292
+ else
1293
+ assert_kind_of BigDecimal, b.my_house_population
1294
+ end
1295
+ assert_equal 3, b.my_house_population
1296
+ assert_kind_of BigDecimal, b.bank_balance
1297
+ assert_equal BigDecimal("1586.43"), b.bank_balance
1298
+ assert_kind_of BigDecimal, b.big_bank_balance
1299
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
1300
+
1301
+ # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
1302
+ # precision/scale explicitly left out. By the SQL standard, numbers
1303
+ # assigned to this field should be truncated but that's seldom respected.
1304
+ if current_adapter?(:PostgreSQLAdapter)
1305
+ # - PostgreSQL changes the SQL spec on columns declared simply as
1306
+ # "decimal" to something more useful: instead of being given a scale
1307
+ # of 0, they take on the compile-time limit for precision and scale,
1308
+ # so the following should succeed unless you have used really wacky
1309
+ # compilation options
1310
+ # - SQLite2 has the default behavior of preserving all data sent in,
1311
+ # so this happens there too
1312
+ assert_kind_of BigDecimal, b.value_of_e
1313
+ assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
1314
+ elsif current_adapter?(:SQLite3Adapter)
1315
+ # - SQLite3 stores a float, in violation of SQL
1316
+ assert_kind_of BigDecimal, b.value_of_e
1317
+ assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001
1318
+ else
1319
+ # - SQL standard is an integer
1320
+ unless current_adapter?(:IBM_DBAdapter)
1321
+ assert_kind_of Fixnum, b.value_of_e
1322
+ else
1323
+ assert_kind_of BigDecimal, b.value_of_e
1324
+ end
1325
+ assert_equal 2, b.value_of_e
1326
+ end
1327
+
1328
+ GiveMeBigNumbers.down
1329
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
1330
+ end
1331
+
1332
+ def test_migrator
1333
+ assert !Person.column_methods_hash.include?(:last_name)
1334
+ assert !Reminder.table_exists?
1335
+
1336
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1337
+
1338
+ assert_equal 3, ActiveRecord::Migrator.current_version
1339
+ Person.reset_column_information
1340
+ assert Person.column_methods_hash.include?(:last_name)
1341
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1342
+ assert_equal "hello world", Reminder.find(:first).content
1343
+
1344
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
1345
+
1346
+ assert_equal 0, ActiveRecord::Migrator.current_version
1347
+ Person.reset_column_information
1348
+ assert !Person.column_methods_hash.include?(:last_name)
1349
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1350
+ end
1351
+
1352
+ def test_filtering_migrations
1353
+ assert !Person.column_methods_hash.include?(:last_name)
1354
+ assert !Reminder.table_exists?
1355
+
1356
+ name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
1357
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
1358
+
1359
+ Person.reset_column_information
1360
+ assert Person.column_methods_hash.include?(:last_name)
1361
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1362
+
1363
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
1364
+
1365
+ Person.reset_column_information
1366
+ assert !Person.column_methods_hash.include?(:last_name)
1367
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1368
+ end
1369
+
1370
+ class MockMigration < ActiveRecord::Migration
1371
+ attr_reader :went_up, :went_down
1372
+ def initialize
1373
+ @went_up = false
1374
+ @went_down = false
1375
+ end
1376
+
1377
+ def up
1378
+ @went_up = true
1379
+ super
1380
+ end
1381
+
1382
+ def down
1383
+ @went_down = true
1384
+ super
1385
+ end
1386
+ end
1387
+
1388
+ def test_instance_based_migration_up
1389
+ migration = MockMigration.new
1390
+ assert !migration.went_up, 'have not gone up'
1391
+ assert !migration.went_down, 'have not gone down'
1392
+
1393
+ migration.migrate :up
1394
+ assert migration.went_up, 'have gone up'
1395
+ assert !migration.went_down, 'have not gone down'
1396
+ end
1397
+
1398
+ def test_instance_based_migration_down
1399
+ migration = MockMigration.new
1400
+ assert !migration.went_up, 'have not gone up'
1401
+ assert !migration.went_down, 'have not gone down'
1402
+
1403
+ migration.migrate :down
1404
+ assert !migration.went_up, 'have gone up'
1405
+ assert migration.went_down, 'have not gone down'
1406
+ end
1407
+
1408
+ def test_migrator_one_up
1409
+ assert !Person.column_methods_hash.include?(:last_name)
1410
+ assert !Reminder.table_exists?
1411
+
1412
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1413
+
1414
+ Person.reset_column_information
1415
+ assert Person.column_methods_hash.include?(:last_name)
1416
+ assert !Reminder.table_exists?
1417
+
1418
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
1419
+
1420
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1421
+ assert_equal "hello world", Reminder.find(:first).content
1422
+ end
1423
+
1424
+ def test_migrator_one_down
1425
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1426
+
1427
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
1428
+
1429
+ Person.reset_column_information
1430
+ assert Person.column_methods_hash.include?(:last_name)
1431
+ assert !Reminder.table_exists?
1432
+ end
1433
+
1434
+ def test_migrator_one_up_one_down
1435
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1436
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1437
+
1438
+ assert !Person.column_methods_hash.include?(:last_name)
1439
+ assert !Reminder.table_exists?
1440
+ end
1441
+
1442
+ def test_migrator_double_up
1443
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1444
+ ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1445
+ assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
1446
+ assert_equal(1, ActiveRecord::Migrator.current_version)
1447
+ end
1448
+
1449
+ def test_migrator_double_down
1450
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1451
+ ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1452
+ ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
1453
+ assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
1454
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1455
+ end
1456
+
1457
+ if ActiveRecord::Base.connection.supports_ddl_transactions?
1458
+ def test_migrator_one_up_with_exception_and_rollback
1459
+ assert !Person.column_methods_hash.include?(:last_name)
1460
+
1461
+ e = assert_raise(StandardError) do
1462
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
1463
+ end
1464
+
1465
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
1466
+
1467
+ Person.reset_column_information
1468
+ assert !Person.column_methods_hash.include?(:last_name)
1469
+ end
1470
+ end
1471
+
1472
+ def test_finds_migrations
1473
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
1474
+
1475
+ [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1476
+ assert_equal migrations[i].version, pair.first
1477
+ assert_equal migrations[i].name, pair.last
1478
+ end
1479
+ end
1480
+
1481
+ def test_finds_migrations_in_subdirectories
1482
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations
1483
+
1484
+ [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1485
+ assert_equal migrations[i].version, pair.first
1486
+ assert_equal migrations[i].name, pair.last
1487
+ end
1488
+ end
1489
+
1490
+ def test_finds_migrations_from_two_directories
1491
+ directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps']
1492
+ migrations = ActiveRecord::Migrator.new(:up, directories).migrations
1493
+
1494
+ [[20090101010101, "PeopleHaveHobbies"],
1495
+ [20090101010202, "PeopleHaveDescriptions"],
1496
+ [20100101010101, "ValidWithTimestampsPeopleHaveLastNames"],
1497
+ [20100201010101, "ValidWithTimestampsWeNeedReminders"],
1498
+ [20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i|
1499
+ assert_equal pair.first, migrations[i].version
1500
+ assert_equal pair.last, migrations[i].name
1501
+ end
1502
+ end
1503
+
1504
+ def test_dump_schema_information_outputs_lexically_ordered_versions
1505
+ migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps'
1506
+ ActiveRecord::Migrator.run(:up, migration_path, 20100301010101)
1507
+ ActiveRecord::Migrator.run(:up, migration_path, 20100201010101)
1508
+
1509
+ schema_info = ActiveRecord::Base.connection.dump_schema_information
1510
+ assert_match(/20100201010101.*20100301010101/m, schema_info)
1511
+ end
1512
+
1513
+ def test_finds_pending_migrations
1514
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
1515
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
1516
+
1517
+ assert_equal 1, migrations.size
1518
+ assert_equal migrations[0].version, 3
1519
+ assert_equal migrations[0].name, 'InterleavedInnocentJointable'
1520
+ end
1521
+
1522
+ def test_relative_migrations
1523
+ list = Dir.chdir(MIGRATIONS_ROOT) do
1524
+ ActiveRecord::Migrator.up("valid/", 1)
1525
+ end
1526
+
1527
+ migration_proxy = list.find { |item|
1528
+ item.name == 'ValidPeopleHaveLastNames'
1529
+ }
1530
+ assert migration_proxy, 'should find pending migration'
1531
+ end
1532
+
1533
+ def test_only_loads_pending_migrations
1534
+ # migrate up to 1
1535
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1536
+
1537
+ proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
1538
+
1539
+ names = proxies.map(&:name)
1540
+ assert !names.include?('ValidPeopleHaveLastNames')
1541
+ assert names.include?('WeNeedReminders')
1542
+ assert names.include?('InnocentJointable')
1543
+ end
1544
+
1545
+ def test_target_version_zero_should_run_only_once
1546
+ # migrate up to 1
1547
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1548
+
1549
+ # migrate down to 0
1550
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1551
+
1552
+ # migrate down to 0 again
1553
+ proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1554
+ assert_equal [], proxies
1555
+ end
1556
+
1557
+ def test_migrator_db_has_no_schema_migrations_table
1558
+ # Oracle adapter raises error if semicolon is present as last character
1559
+ if current_adapter?(:OracleAdapter)
1560
+ ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
1561
+ else
1562
+ ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
1563
+ end
1564
+ assert_nothing_raised do
1565
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1566
+ end
1567
+ end
1568
+
1569
+ def test_migrator_verbosity
1570
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1571
+ assert_not_equal 0, ActiveRecord::Migration.message_count
1572
+ ActiveRecord::Migration.message_count = 0
1573
+
1574
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1575
+ assert_not_equal 0, ActiveRecord::Migration.message_count
1576
+ ActiveRecord::Migration.message_count = 0
1577
+ end
1578
+
1579
+ def test_migrator_verbosity_off
1580
+ ActiveRecord::Migration.verbose = false
1581
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1582
+ assert_equal 0, ActiveRecord::Migration.message_count
1583
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1584
+ assert_equal 0, ActiveRecord::Migration.message_count
1585
+ end
1586
+
1587
+ def test_migrator_going_down_due_to_version_target
1588
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1589
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1590
+
1591
+ assert !Person.column_methods_hash.include?(:last_name)
1592
+ assert !Reminder.table_exists?
1593
+
1594
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1595
+
1596
+ Person.reset_column_information
1597
+ assert Person.column_methods_hash.include?(:last_name)
1598
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1599
+ assert_equal "hello world", Reminder.find(:first).content
1600
+ end
1601
+
1602
+ def test_migrator_rollback
1603
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1604
+ assert_equal(3, ActiveRecord::Migrator.current_version)
1605
+
1606
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1607
+ assert_equal(2, ActiveRecord::Migrator.current_version)
1608
+
1609
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1610
+ assert_equal(1, ActiveRecord::Migrator.current_version)
1611
+
1612
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1613
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1614
+
1615
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1616
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1617
+ end
1618
+
1619
+ def test_migrator_forward
1620
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1621
+ assert_equal(1, ActiveRecord::Migrator.current_version)
1622
+
1623
+ ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2)
1624
+ assert_equal(3, ActiveRecord::Migrator.current_version)
1625
+
1626
+ ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid")
1627
+ assert_equal(3, ActiveRecord::Migrator.current_version)
1628
+ end
1629
+
1630
+ def test_get_all_versions
1631
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1632
+ assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions)
1633
+
1634
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1635
+ assert_equal([1,2], ActiveRecord::Migrator.get_all_versions)
1636
+
1637
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1638
+ assert_equal([1], ActiveRecord::Migrator.get_all_versions)
1639
+
1640
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1641
+ assert_equal([], ActiveRecord::Migrator.get_all_versions)
1642
+ end
1643
+
1644
+ def test_schema_migrations_table_name
1645
+ ActiveRecord::Base.table_name_prefix = "prefix_"
1646
+ ActiveRecord::Base.table_name_suffix = "_suffix"
1647
+ Reminder.reset_table_name
1648
+ assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
1649
+ ActiveRecord::Base.table_name_prefix = ""
1650
+ ActiveRecord::Base.table_name_suffix = ""
1651
+ Reminder.reset_table_name
1652
+ assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
1653
+ ensure
1654
+ ActiveRecord::Base.table_name_prefix = ""
1655
+ ActiveRecord::Base.table_name_suffix = ""
1656
+ end
1657
+
1658
+ def test_proper_table_name
1659
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
1660
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
1661
+ assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
1662
+ Reminder.reset_table_name
1663
+ assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
1664
+
1665
+ # Use the model's own prefix/suffix if a model is given
1666
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
1667
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
1668
+ Reminder.table_name_prefix = 'prefix_'
1669
+ Reminder.table_name_suffix = '_suffix'
1670
+ Reminder.reset_table_name
1671
+ assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
1672
+ Reminder.table_name_prefix = ''
1673
+ Reminder.table_name_suffix = ''
1674
+ Reminder.reset_table_name
1675
+
1676
+ # Use AR::Base's prefix/suffix if string or symbol is given
1677
+ ActiveRecord::Base.table_name_prefix = "prefix_"
1678
+ ActiveRecord::Base.table_name_suffix = "_suffix"
1679
+ Reminder.reset_table_name
1680
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
1681
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
1682
+ ActiveRecord::Base.table_name_prefix = ""
1683
+ ActiveRecord::Base.table_name_suffix = ""
1684
+ Reminder.reset_table_name
1685
+ end
1686
+
1687
+ def test_rename_table_with_prefix_and_suffix
1688
+ assert !Thing.table_exists?
1689
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
1690
+ ActiveRecord::Base.table_name_suffix = '_suffix'
1691
+ Thing.reset_table_name
1692
+ Thing.reset_sequence_name
1693
+ WeNeedThings.up
1694
+
1695
+ assert Thing.create("content" => "hello world")
1696
+ assert_equal "hello world", Thing.find(:first).content
1697
+
1698
+ RenameThings.up
1699
+ Thing.table_name = "prefix_awesome_things_suffix"
1700
+
1701
+ assert_equal "hello world", Thing.find(:first).content
1702
+ ensure
1703
+ ActiveRecord::Base.table_name_prefix = ''
1704
+ ActiveRecord::Base.table_name_suffix = ''
1705
+ Thing.reset_table_name
1706
+ Thing.reset_sequence_name
1707
+ end
1708
+
1709
+ def test_add_drop_table_with_prefix_and_suffix
1710
+ assert !Reminder.table_exists?
1711
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
1712
+ ActiveRecord::Base.table_name_suffix = '_suffix'
1713
+ Reminder.reset_table_name
1714
+ Reminder.reset_sequence_name
1715
+ WeNeedReminders.up
1716
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1717
+ assert_equal "hello world", Reminder.find(:first).content
1718
+
1719
+ WeNeedReminders.down
1720
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1721
+ ensure
1722
+ ActiveRecord::Base.table_name_prefix = ''
1723
+ ActiveRecord::Base.table_name_suffix = ''
1724
+ Reminder.reset_table_name
1725
+ Reminder.reset_sequence_name
1726
+ end
1727
+
1728
+ def test_create_table_with_binary_column
1729
+ Person.connection.drop_table :binary_testings rescue nil
1730
+
1731
+ assert_nothing_raised {
1732
+ Person.connection.create_table :binary_testings do |t|
1733
+ t.column "data", :binary, :null => false
1734
+ end
1735
+ }
1736
+
1737
+ columns = Person.connection.columns(:binary_testings)
1738
+ data_column = columns.detect { |c| c.name == "data" }
1739
+
1740
+ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
1741
+ assert_equal '', data_column.default
1742
+ else
1743
+ assert_nil data_column.default
1744
+ end
1745
+
1746
+ Person.connection.drop_table :binary_testings rescue nil
1747
+ end
1748
+
1749
+ def test_migrator_with_duplicates
1750
+ assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
1751
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
1752
+ end
1753
+ end
1754
+
1755
+ def test_migrator_with_duplicate_names
1756
+ assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
1757
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
1758
+ end
1759
+ end
1760
+
1761
+ def test_migrator_with_missing_version_numbers
1762
+ assert_raise(ActiveRecord::UnknownMigrationVersionError) do
1763
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
1764
+ end
1765
+ end
1766
+
1767
+ def test_create_table_with_custom_sequence_name
1768
+ return unless current_adapter? :OracleAdapter
1769
+
1770
+ # table name is 29 chars, the standard sequence name will
1771
+ # be 33 chars and should be shortened
1772
+ assert_nothing_raised do
1773
+ begin
1774
+ Person.connection.create_table :table_with_name_thats_just_ok do |t|
1775
+ t.column :foo, :string, :null => false
1776
+ end
1777
+ ensure
1778
+ Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
1779
+ end
1780
+ end
1781
+
1782
+ # should be all good w/ a custom sequence name
1783
+ assert_nothing_raised do
1784
+ begin
1785
+ Person.connection.create_table :table_with_name_thats_just_ok,
1786
+ :sequence_name => 'suitably_short_seq' do |t|
1787
+ t.column :foo, :string, :null => false
1788
+ end
1789
+
1790
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
1791
+
1792
+ ensure
1793
+ Person.connection.drop_table :table_with_name_thats_just_ok,
1794
+ :sequence_name => 'suitably_short_seq' rescue nil
1795
+ end
1796
+ end
1797
+
1798
+ # confirm the custom sequence got dropped
1799
+ assert_raise(ActiveRecord::StatementInvalid) do
1800
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
1801
+ end
1802
+ end
1803
+
1804
+ protected
1805
+ def with_env_tz(new_tz = 'US/Eastern')
1806
+ old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1807
+ yield
1808
+ ensure
1809
+ old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1810
+ end
1811
+
1812
+ end
1813
+
1814
+ class MigrationLoggerTest < ActiveRecord::TestCase
1815
+ def test_migration_should_be_run_without_logger
1816
+ previous_logger = ActiveRecord::Base.logger
1817
+ ActiveRecord::Base.logger = nil
1818
+ assert_nothing_raised do
1819
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1820
+ end
1821
+ ensure
1822
+ ActiveRecord::Base.logger = previous_logger
1823
+ end
1824
+ end
1825
+
1826
+ class InterleavedMigrationsTest < ActiveRecord::TestCase
1827
+ def test_migrator_interleaved_migrations
1828
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
1829
+
1830
+ assert_nothing_raised do
1831
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
1832
+ end
1833
+
1834
+ Person.reset_column_information
1835
+ assert Person.column_methods_hash.include?(:last_name)
1836
+
1837
+ assert_nothing_raised do
1838
+ proxies = ActiveRecord::Migrator.down(
1839
+ MIGRATIONS_ROOT + "/interleaved/pass_3")
1840
+ names = proxies.map(&:name)
1841
+ assert names.include?('InterleavedPeopleHaveLastNames')
1842
+ assert names.include?('InterleavedInnocentJointable')
1843
+ end
1844
+ end
1845
+ end
1846
+
1847
+ class ReservedWordsMigrationTest < ActiveRecord::TestCase
1848
+ def test_drop_index_from_table_named_values
1849
+ connection = Person.connection
1850
+ connection.create_table :values, :force => true do |t|
1851
+ t.integer :value
1852
+ end
1853
+
1854
+ assert_nothing_raised do
1855
+ connection.add_index :values, :value
1856
+ connection.remove_index :values, :column => :value
1857
+ end
1858
+
1859
+ connection.drop_table :values rescue nil
1860
+ end
1861
+ end
1862
+
1863
+
1864
+ class ChangeTableMigrationsTest < ActiveRecord::TestCase
1865
+ def setup
1866
+ @connection = Person.connection
1867
+ @connection.create_table :delete_me, :force => true do |t|
1868
+ end
1869
+ end
1870
+
1871
+ def teardown
1872
+ Person.connection.drop_table :delete_me rescue nil
1873
+ end
1874
+
1875
+ def test_references_column_type_adds_id
1876
+ with_change_table do |t|
1877
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1878
+ t.references :customer
1879
+ end
1880
+ end
1881
+
1882
+ def test_remove_references_column_type_removes_id
1883
+ with_change_table do |t|
1884
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1885
+ t.remove_references :customer
1886
+ end
1887
+ end
1888
+
1889
+ def test_add_belongs_to_works_like_add_references
1890
+ with_change_table do |t|
1891
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1892
+ t.belongs_to :customer
1893
+ end
1894
+ end
1895
+
1896
+ def test_remove_belongs_to_works_like_remove_references
1897
+ with_change_table do |t|
1898
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1899
+ t.remove_belongs_to :customer
1900
+ end
1901
+ end
1902
+
1903
+ def test_references_column_type_with_polymorphic_adds_type
1904
+ with_change_table do |t|
1905
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1906
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1907
+ t.references :taggable, :polymorphic => true
1908
+ end
1909
+ end
1910
+
1911
+ def test_remove_references_column_type_with_polymorphic_removes_type
1912
+ with_change_table do |t|
1913
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1914
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1915
+ t.remove_references :taggable, :polymorphic => true
1916
+ end
1917
+ end
1918
+
1919
+ def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1920
+ with_change_table do |t|
1921
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1922
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1923
+ t.references :taggable, :polymorphic => true, :null => false
1924
+ end
1925
+ end
1926
+
1927
+ def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1928
+ with_change_table do |t|
1929
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1930
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1931
+ t.remove_references :taggable, :polymorphic => true, :null => false
1932
+ end
1933
+ end
1934
+
1935
+ def test_timestamps_creates_updated_at_and_created_at
1936
+ with_change_table do |t|
1937
+ @connection.expects(:add_timestamps).with(:delete_me)
1938
+ t.timestamps
1939
+ end
1940
+ end
1941
+
1942
+ def test_remove_timestamps_creates_updated_at_and_created_at
1943
+ with_change_table do |t|
1944
+ @connection.expects(:remove_timestamps).with(:delete_me)
1945
+ t.remove_timestamps
1946
+ end
1947
+ end
1948
+
1949
+ def string_column
1950
+ if current_adapter?(:PostgreSQLAdapter)
1951
+ "character varying(255)"
1952
+ elsif current_adapter?(:OracleAdapter)
1953
+ 'VARCHAR2(255)'
1954
+ else
1955
+ 'varchar(255)'
1956
+ end
1957
+ end
1958
+
1959
+ def integer_column
1960
+ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
1961
+ 'int(11)'
1962
+ elsif current_adapter?(:OracleAdapter)
1963
+ 'NUMBER(38)'
1964
+ else
1965
+ 'integer'
1966
+ end
1967
+ end
1968
+
1969
+ def test_integer_creates_integer_column
1970
+ with_change_table do |t|
1971
+ @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
1972
+ @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
1973
+ t.integer :foo, :bar
1974
+ end
1975
+ end
1976
+
1977
+ def test_string_creates_string_column
1978
+ with_change_table do |t|
1979
+ @connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
1980
+ @connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
1981
+ t.string :foo, :bar
1982
+ end
1983
+ end
1984
+
1985
+ def test_column_creates_column
1986
+ with_change_table do |t|
1987
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1988
+ t.column :bar, :integer
1989
+ end
1990
+ end
1991
+
1992
+ def test_column_creates_column_with_options
1993
+ with_change_table do |t|
1994
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1995
+ t.column :bar, :integer, :null => false
1996
+ end
1997
+ end
1998
+
1999
+ def test_index_creates_index
2000
+ with_change_table do |t|
2001
+ @connection.expects(:add_index).with(:delete_me, :bar, {})
2002
+ t.index :bar
2003
+ end
2004
+ end
2005
+
2006
+ def test_index_creates_index_with_options
2007
+ with_change_table do |t|
2008
+ @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
2009
+ t.index :bar, :unique => true
2010
+ end
2011
+ end
2012
+
2013
+ def test_index_exists
2014
+ with_change_table do |t|
2015
+ @connection.expects(:index_exists?).with(:delete_me, :bar, {})
2016
+ t.index_exists?(:bar)
2017
+ end
2018
+ end
2019
+
2020
+ def test_index_exists_with_options
2021
+ with_change_table do |t|
2022
+ @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true})
2023
+ t.index_exists?(:bar, :unique => true)
2024
+ end
2025
+ end
2026
+
2027
+ def test_change_changes_column
2028
+ with_change_table do |t|
2029
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
2030
+ t.change :bar, :string
2031
+ end
2032
+ end
2033
+
2034
+ def test_change_changes_column_with_options
2035
+ with_change_table do |t|
2036
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
2037
+ t.change :bar, :string, :null => true
2038
+ end
2039
+ end
2040
+
2041
+ def test_change_default_changes_column
2042
+ with_change_table do |t|
2043
+ @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
2044
+ t.change_default :bar, :string
2045
+ end
2046
+ end
2047
+
2048
+ def test_remove_drops_single_column
2049
+ with_change_table do |t|
2050
+ @connection.expects(:remove_column).with(:delete_me, [:bar])
2051
+ t.remove :bar
2052
+ end
2053
+ end
2054
+
2055
+ def test_remove_drops_multiple_columns
2056
+ with_change_table do |t|
2057
+ @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
2058
+ t.remove :bar, :baz
2059
+ end
2060
+ end
2061
+
2062
+ def test_remove_index_removes_index_with_options
2063
+ with_change_table do |t|
2064
+ @connection.expects(:remove_index).with(:delete_me, {:unique => true})
2065
+ t.remove_index :unique => true
2066
+ end
2067
+ end
2068
+
2069
+ def test_rename_renames_column
2070
+ with_change_table do |t|
2071
+ @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
2072
+ t.rename :bar, :baz
2073
+ end
2074
+ end
2075
+
2076
+ protected
2077
+ def with_change_table
2078
+ Person.connection.change_table :delete_me do |t|
2079
+ yield t
2080
+ end
2081
+ end
2082
+ end
2083
+
2084
+ if ActiveRecord::Base.connection.supports_bulk_alter?
2085
+ class BulkAlterTableMigrationsTest < ActiveRecord::TestCase
2086
+ def setup
2087
+ @connection = Person.connection
2088
+ @connection.create_table(:delete_me, :force => true) {|t| }
2089
+ end
2090
+
2091
+ def teardown
2092
+ Person.connection.drop_table(:delete_me) rescue nil
2093
+ end
2094
+
2095
+ def test_adding_multiple_columns
2096
+ assert_queries(1) do
2097
+ with_bulk_change_table do |t|
2098
+ t.column :name, :string
2099
+ t.string :qualification, :experience
2100
+ t.integer :age, :default => 0
2101
+ t.date :birthdate
2102
+ t.timestamps
2103
+ end
2104
+ end
2105
+
2106
+ assert_equal 8, columns.size
2107
+ [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type }
2108
+ assert_equal 0, column(:age).default
2109
+ end
2110
+
2111
+ def test_removing_columns
2112
+ with_bulk_change_table do |t|
2113
+ t.string :qualification, :experience
2114
+ end
2115
+
2116
+ [:qualification, :experience].each {|c| assert column(c) }
2117
+
2118
+ assert_queries(1) do
2119
+ with_bulk_change_table do |t|
2120
+ t.remove :qualification, :experience
2121
+ t.string :qualification_experience
2122
+ end
2123
+ end
2124
+
2125
+ [:qualification, :experience].each {|c| assert ! column(c) }
2126
+ assert column(:qualification_experience)
2127
+ end
2128
+
2129
+ def test_adding_indexes
2130
+ with_bulk_change_table do |t|
2131
+ t.string :username
2132
+ t.string :name
2133
+ t.integer :age
2134
+ end
2135
+
2136
+ # Adding an index fires a query every time to check if an index already exists or not
2137
+ assert_queries(3) do
2138
+ with_bulk_change_table do |t|
2139
+ t.index :username, :unique => true, :name => :awesome_username_index
2140
+ t.index [:name, :age]
2141
+ end
2142
+ end
2143
+
2144
+ assert_equal 2, indexes.size
2145
+
2146
+ name_age_index = index(:index_delete_me_on_name_and_age)
2147
+ assert_equal ['name', 'age'].sort, name_age_index.columns.sort
2148
+ assert ! name_age_index.unique
2149
+
2150
+ assert index(:awesome_username_index).unique
2151
+ end
2152
+
2153
+ def test_removing_index
2154
+ with_bulk_change_table do |t|
2155
+ t.string :name
2156
+ t.index :name
2157
+ end
2158
+
2159
+ assert index(:index_delete_me_on_name)
2160
+
2161
+ assert_queries(3) do
2162
+ with_bulk_change_table do |t|
2163
+ t.remove_index :name
2164
+ t.index :name, :name => :new_name_index, :unique => true
2165
+ end
2166
+ end
2167
+
2168
+ assert ! index(:index_delete_me_on_name)
2169
+
2170
+ new_name_index = index(:new_name_index)
2171
+ assert new_name_index.unique
2172
+ end
2173
+
2174
+ def test_changing_columns
2175
+ with_bulk_change_table do |t|
2176
+ t.string :name
2177
+ t.date :birthdate
2178
+ end
2179
+
2180
+ assert ! column(:name).default
2181
+ assert_equal :date, column(:birthdate).type
2182
+
2183
+ # One query for columns (delete_me table)
2184
+ # One query for primary key (delete_me table)
2185
+ # One query to do the bulk change
2186
+ assert_queries(3) do
2187
+ with_bulk_change_table do |t|
2188
+ t.change :name, :string, :default => 'NONAME'
2189
+ t.change :birthdate, :datetime
2190
+ end
2191
+ end
2192
+
2193
+ assert_equal 'NONAME', column(:name).default
2194
+ assert_equal :datetime, column(:birthdate).type
2195
+ end
2196
+
2197
+ protected
2198
+
2199
+ def with_bulk_change_table
2200
+ # Reset columns/indexes cache as we're changing the table
2201
+ @columns = @indexes = nil
2202
+
2203
+ Person.connection.change_table(:delete_me, :bulk => true) do |t|
2204
+ yield t
2205
+ end
2206
+ end
2207
+
2208
+ def column(name)
2209
+ columns.detect {|c| c.name == name.to_s }
2210
+ end
2211
+
2212
+ def columns
2213
+ @columns ||= Person.connection.columns('delete_me')
2214
+ end
2215
+
2216
+ def index(name)
2217
+ indexes.detect {|i| i.name == name.to_s }
2218
+ end
2219
+
2220
+ def indexes
2221
+ @indexes ||= Person.connection.indexes('delete_me')
2222
+ end
2223
+ end # AlterTableMigrationsTest
2224
+
2225
+ end
2226
+
2227
+ class CopyMigrationsTest < ActiveRecord::TestCase
2228
+ def setup
2229
+ end
2230
+
2231
+ def clear
2232
+ ActiveRecord::Base.timestamped_migrations = true
2233
+ to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
2234
+ File.delete(*to_delete)
2235
+ end
2236
+
2237
+ def test_copying_migrations_without_timestamps
2238
+ ActiveRecord::Base.timestamped_migrations = false
2239
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
2240
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2241
+
2242
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
2243
+ assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
2244
+ assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
2245
+ assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename)
2246
+
2247
+ expected = "# This migration comes from bukkits (originally 1)"
2248
+ assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp
2249
+
2250
+ files_count = Dir[@migrations_path + "/*.rb"].length
2251
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"})
2252
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2253
+ assert copied.empty?
2254
+ ensure
2255
+ clear
2256
+ end
2257
+
2258
+ def test_copying_migrations_without_timestamps_from_2_sources
2259
+ ActiveRecord::Base.timestamped_migrations = false
2260
+ @migrations_path = MIGRATIONS_ROOT + "/valid"
2261
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2262
+
2263
+ sources = ActiveSupport::OrderedHash.new
2264
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
2265
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
2266
+ ActiveRecord::Migration.copy(@migrations_path, sources)
2267
+ assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb")
2268
+ assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb")
2269
+ assert File.exists?(@migrations_path + "/6_create_articles.omg.rb")
2270
+ assert File.exists?(@migrations_path + "/7_create_comments.omg.rb")
2271
+
2272
+ files_count = Dir[@migrations_path + "/*.rb"].length
2273
+ ActiveRecord::Migration.copy(@migrations_path, sources)
2274
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2275
+ ensure
2276
+ clear
2277
+ end
2278
+
2279
+ def test_copying_migrations_with_timestamps
2280
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2281
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2282
+
2283
+ Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2284
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2285
+ assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2286
+ assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2287
+ expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb",
2288
+ @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"]
2289
+ assert_equal expected, copied.map(&:filename)
2290
+
2291
+ files_count = Dir[@migrations_path + "/*.rb"].length
2292
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2293
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2294
+ assert copied.empty?
2295
+ end
2296
+ ensure
2297
+ clear
2298
+ end
2299
+
2300
+ def test_copying_migrations_with_timestamps_from_2_sources
2301
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2302
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2303
+
2304
+ sources = ActiveSupport::OrderedHash.new
2305
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2306
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
2307
+
2308
+ Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2309
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources)
2310
+ assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2311
+ assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2312
+ assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb")
2313
+ assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb")
2314
+ assert_equal 4, copied.length
2315
+
2316
+ files_count = Dir[@migrations_path + "/*.rb"].length
2317
+ ActiveRecord::Migration.copy(@migrations_path, sources)
2318
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2319
+ end
2320
+ ensure
2321
+ clear
2322
+ end
2323
+
2324
+ def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future
2325
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2326
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2327
+
2328
+ Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
2329
+ ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2330
+ assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb")
2331
+ assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb")
2332
+
2333
+ files_count = Dir[@migrations_path + "/*.rb"].length
2334
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2335
+ assert_equal files_count, Dir[@migrations_path + "/*.rb"].length
2336
+ assert copied.empty?
2337
+ end
2338
+ ensure
2339
+ clear
2340
+ end
2341
+
2342
+ def test_skipping_migrations
2343
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2344
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2345
+
2346
+ sources = ActiveSupport::OrderedHash.new
2347
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2348
+ sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
2349
+
2350
+ skipped = []
2351
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
2352
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2353
+ assert_equal 2, copied.length
2354
+
2355
+ assert_equal 1, skipped.length
2356
+ assert_equal ["omg PeopleHaveHobbies"], skipped
2357
+ ensure
2358
+ clear
2359
+ end
2360
+
2361
+ def test_skip_is_not_called_if_migrations_are_from_the_same_plugin
2362
+ @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
2363
+ @existing_migrations = Dir[@migrations_path + "/*.rb"]
2364
+
2365
+ sources = ActiveSupport::OrderedHash.new
2366
+ sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
2367
+
2368
+ skipped = []
2369
+ on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
2370
+ copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2371
+ ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip)
2372
+
2373
+ assert_equal 2, copied.length
2374
+ assert_equal 0, skipped.length
2375
+ ensure
2376
+ clear
2377
+ end
2378
+
2379
+ def test_copying_migrations_to_non_existing_directory
2380
+ @migrations_path = MIGRATIONS_ROOT + "/non_existing"
2381
+ @existing_migrations = []
2382
+
2383
+ Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2384
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2385
+ assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2386
+ assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2387
+ assert_equal 2, copied.length
2388
+ end
2389
+ ensure
2390
+ clear
2391
+ Dir.delete(@migrations_path)
2392
+ end
2393
+
2394
+ def test_copying_migrations_to_empty_directory
2395
+ @migrations_path = MIGRATIONS_ROOT + "/empty"
2396
+ @existing_migrations = []
2397
+
2398
+ Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
2399
+ copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"})
2400
+ assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb")
2401
+ assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb")
2402
+ assert_equal 2, copied.length
2403
+ end
2404
+ ensure
2405
+ clear
2406
+ end
2407
+ end
2408
+ end