ibm_db 1.1.1-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGES +155 -0
  2. data/LICENSE +18 -0
  3. data/MANIFEST +14 -0
  4. data/README +274 -0
  5. data/ext/Makefile.nt32 +181 -0
  6. data/ext/extconf.rb +58 -0
  7. data/ext/ibm_db.c +6553 -0
  8. data/ext/ruby_ibm_db.h +214 -0
  9. data/init.rb +42 -0
  10. data/lib/IBM_DB.rb +2 -0
  11. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +2218 -0
  12. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  13. data/lib/mswin32/ibm_db.so +0 -0
  14. data/test/cases/adapter_test.rb +180 -0
  15. data/test/cases/associations/cascaded_eager_loading_test.rb +133 -0
  16. data/test/cases/associations/eager_test.rb +842 -0
  17. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +874 -0
  18. data/test/cases/associations/has_many_through_associations_test.rb +281 -0
  19. data/test/cases/associations/join_model_test.rb +801 -0
  20. data/test/cases/attribute_methods_test.rb +312 -0
  21. data/test/cases/base_test.rb +2114 -0
  22. data/test/cases/calculations_test.rb +346 -0
  23. data/test/cases/finder_test.rb +1092 -0
  24. data/test/cases/fixtures_test.rb +660 -0
  25. data/test/cases/migration_test.rb +1618 -0
  26. data/test/cases/schema_dumper_test.rb +197 -0
  27. data/test/cases/validations_test.rb +1604 -0
  28. data/test/connections/native_ibm_db/connection.rb +40 -0
  29. data/test/ibm_db_test.rb +25 -0
  30. data/test/models/warehouse_thing.rb +5 -0
  31. data/test/schema/i5/ibm_db_specific_schema.rb +134 -0
  32. data/test/schema/ids/ibm_db_specific_schema.rb +137 -0
  33. data/test/schema/luw/ibm_db_specific_schema.rb +134 -0
  34. data/test/schema/schema.rb +499 -0
  35. data/test/schema/zOS/ibm_db_specific_schema.rb +205 -0
  36. metadata +115 -0
@@ -0,0 +1,1618 @@
1
+ require "cases/helper"
2
+ require 'bigdecimal/util'
3
+ require 'mocha'
4
+
5
+ require 'models/person'
6
+ require 'models/topic'
7
+ require 'models/developer'
8
+
9
+ require MIGRATIONS_ROOT + "/valid/1_people_have_last_names"
10
+ require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
11
+ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
12
+ require MIGRATIONS_ROOT + "/interleaved/pass_3/2_i_raise_on_down"
13
+
14
+ if ActiveRecord::Base.connection.supports_migrations?
15
+ class BigNumber < ActiveRecord::Base; end
16
+
17
+ class Reminder < ActiveRecord::Base; end
18
+
19
+ class ActiveRecord::Migration
20
+ class <<self
21
+ attr_accessor :message_count
22
+ def puts(text="")
23
+ self.message_count ||= 0
24
+ self.message_count += 1
25
+ end
26
+ end
27
+ end
28
+
29
+ class MigrationTest < ActiveRecord::TestCase
30
+ self.use_transactional_fixtures = false
31
+
32
+ if (current_adapter?(:IBM_DBAdapter))
33
+ #Rename is supported only for server zOS 9 , DB2 COBRA and Informix
34
+ server_type = ActiveRecord::Base.connection.servertype.class.name
35
+ @ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
36
+ server_type.class.name.include?('::IBM_IDS') ||
37
+ (server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
38
+ end
39
+
40
+ fixtures :people
41
+
42
+ def setup
43
+ ActiveRecord::Migration.verbose = true
44
+ PeopleHaveLastNames.message_count = 0
45
+ end
46
+
47
+ def teardown
48
+ ActiveRecord::Base.connection.initialize_schema_migrations_table
49
+ ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
50
+
51
+ %w(reminders people_reminders prefix_reminders_suffix).each do |table|
52
+ Reminder.connection.drop_table(table) rescue nil
53
+ end
54
+ Reminder.reset_column_information
55
+
56
+ %w(last_name key bio age height wealth birthday favorite_day
57
+ moment_of_truth male administrator funny).each do |column|
58
+ Person.connection.remove_column('people', column) rescue nil
59
+ end
60
+ Person.connection.remove_column("people", "first_name") rescue nil
61
+ Person.connection.remove_column("people", "middle_name") rescue nil
62
+ Person.connection.add_column("people", "first_name", :string, :limit => 40)
63
+ Person.reset_column_information
64
+ end
65
+
66
+ def test_add_index
67
+ # Limit size of last_name and key columns to support Firebird index limitations
68
+ Person.connection.add_column "people", "last_name", :string, :limit => 100
69
+ Person.connection.add_column "people", "key", :string, :limit => 100
70
+ Person.connection.add_column "people", "administrator", :boolean
71
+
72
+ assert_nothing_raised { Person.connection.add_index("people", "last_name") }
73
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
74
+
75
+ # Orcl nds shrt indx nms. Sybs 2.
76
+ # OpenBase does not have named indexes. You must specify a single column name
77
+ unless current_adapter?(:OracleAdapter, :SybaseAdapter, :OpenBaseAdapter)
78
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
79
+ assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
80
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
81
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
82
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
83
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
84
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
85
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
86
+ end
87
+
88
+ # quoting
89
+ # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
90
+ # OpenBase does not have named indexes. You must specify a single column name
91
+ unless current_adapter?(:OpenBaseAdapter)
92
+ unless current_adapter?(:IBM_DBAdapter)
93
+ 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)
94
+ else
95
+ Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'first_name'}" #some databases (including sqlite2 won't add a unique index if existing data non unique)
96
+ end
97
+ assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
98
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
99
+ end
100
+
101
+ # Sybase adapter does not support indexes on :boolean columns
102
+ # OpenBase does not have named indexes. You must specify a single column
103
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
104
+ assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
105
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
106
+ end
107
+ end
108
+
109
+ def testing_table_with_only_foo_attribute
110
+ Person.connection.create_table :testings, :id => false do |t|
111
+ t.column :foo, :string
112
+ end
113
+
114
+ yield Person.connection
115
+ ensure
116
+ Person.connection.drop_table :testings rescue nil
117
+ end
118
+ protected :testing_table_with_only_foo_attribute
119
+
120
+ def test_create_table_without_id
121
+ testing_table_with_only_foo_attribute do |connection|
122
+ assert_equal connection.columns(:testings).size, 1
123
+ end
124
+ end
125
+
126
+ unless current_adapter?(:IBM_DBAdapter)
127
+ # Cannot add a primary key to a table with some rows already in it as it violates the unique constraint
128
+ # Secondly GENERATED BY DEFAULT AS IDENTITY cannot be applied in a alter table command.
129
+ # as this will be wrong sql syntax for DB2
130
+ def test_add_column_with_primary_key_attribute
131
+ testing_table_with_only_foo_attribute do |connection|
132
+ assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
133
+ assert_equal connection.columns(:testings).size, 2
134
+ end
135
+ end
136
+ end
137
+
138
+ def test_create_table_adds_id
139
+ Person.connection.create_table :testings do |t|
140
+ t.column :foo, :string
141
+ end
142
+
143
+ assert_equal %w(foo id),
144
+ Person.connection.columns(:testings).map { |c| c.name }.sort
145
+ ensure
146
+ Person.connection.drop_table :testings rescue nil
147
+ end
148
+
149
+ def test_create_table_with_not_null_column
150
+ assert_nothing_raised do
151
+ Person.connection.create_table :testings do |t|
152
+ t.column :foo, :string, :null => false
153
+ end
154
+ end
155
+
156
+ assert_raise(ActiveRecord::StatementInvalid) do
157
+ Person.connection.execute "insert into testings (foo) values (NULL)"
158
+ end
159
+ ensure
160
+ Person.connection.drop_table :testings rescue nil
161
+ end
162
+
163
+ def test_create_table_with_defaults
164
+ # MySQL doesn't allow defaults on TEXT or BLOB columns.
165
+ mysql = current_adapter?(:MysqlAdapter)
166
+ ibm_ids_zOS = ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')||
167
+ ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_DB2_ZOS')
168
+
169
+ Person.connection.create_table :testings do |t|
170
+ t.column :one, :string, :default => "hello"
171
+ t.column :two, :boolean, :default => true
172
+ t.column :three, :boolean, :default => false
173
+ t.column :four, :integer, :default => 1
174
+ t.column :five, :text, :default => "hello" unless mysql || ibm_ids_zOS
175
+ end
176
+
177
+ columns = Person.connection.columns(:testings)
178
+ one = columns.detect { |c| c.name == "one" }
179
+ two = columns.detect { |c| c.name == "two" }
180
+ three = columns.detect { |c| c.name == "three" }
181
+ four = columns.detect { |c| c.name == "four" }
182
+ five = columns.detect { |c| c.name == "five" } unless mysql || ibm_ids_zOS
183
+
184
+ assert_equal "hello", one.default
185
+ assert_equal true, two.default
186
+ assert_equal false, three.default
187
+ assert_equal 1, four.default
188
+ assert_equal "hello", five.default unless mysql || ibm_ids_zOS
189
+
190
+ ensure
191
+ Person.connection.drop_table :testings rescue nil
192
+ end
193
+
194
+ if current_adapter?(:IBM_DBAdapter)
195
+ def test_no_limits_datatypes_IBM_DB
196
+ ibm_ids = ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
197
+ clasz = Class.new(ActiveRecord::Base)
198
+ clasz.table_name = 'test_no_limits_datatypes_IBM_DB'
199
+ assert_nothing_raised do
200
+ clasz.connection.create_table clasz.table_name do |t|
201
+ t.column "test_varchar", :string, :limit => 10
202
+ t.column "test_integer", :integer, :limit => 5
203
+ t.column "test_boolean", :boolean, :limit => 5
204
+ t.column "test_double", :double, :limit => 10
205
+ t.column "test_date", :date, :limit => 10
206
+ t.column "test_time", :time, :limit => 10
207
+ t.column "test_tstamp", :timestamp, :limit => 10
208
+ t.column "test_xml", :xml, :limit => 10 unless ibm_ids
209
+ t.column "test_clob", :text, :limit => 10000
210
+ t.column "test_decfloat", :decfloat, :limit => 100
211
+ end
212
+ end
213
+ ensure
214
+ clasz.connection.drop_table(clasz.table_name) rescue nil
215
+ end
216
+
217
+ #Sexy migration test for column of type xml and char
218
+ def test_short_hand_migrations_for_ibm_db_datatypes
219
+ ibm_ids = ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
220
+ clasz = Class.new(ActiveRecord::Base)
221
+ clasz.table_name = 'test_short_hand_migrations'
222
+ assert_nothing_raised do
223
+ clasz.connection.create_table clasz.table_name do |t|
224
+ t.xml :xml_col unless ibm_ids
225
+ t.char :char_col, :limit=>10
226
+ t.decfloat :dec_col, :precision=>16
227
+ end
228
+ end
229
+ assert_nothing_raised do
230
+ clasz.connection.change_table clasz.table_name do |t|
231
+ t.xml :xml_col1 unless ibm_ids
232
+ t.char :char_col1, :limit=>50
233
+ t.decfloat :dec_col1, :precision=>34
234
+ end
235
+ end
236
+ ensure
237
+ clasz.connection.drop_table(clasz.table_name) rescue nil
238
+ end
239
+ end
240
+
241
+ def test_create_table_with_limits
242
+ assert_nothing_raised do
243
+ Person.connection.create_table :testings do |t|
244
+ t.column :foo, :string, :limit => 255
245
+
246
+ t.column :default_int, :integer
247
+
248
+ t.column :one_int, :integer, :limit => 1
249
+ t.column :four_int, :integer, :limit => 4
250
+ t.column :eight_int, :integer, :limit => 8
251
+ t.column :eleven_int, :integer, :limit => 11
252
+ end
253
+ end
254
+
255
+ columns = Person.connection.columns(:testings)
256
+ foo = columns.detect { |c| c.name == "foo" }
257
+ assert_equal 255, foo.limit
258
+
259
+ default = columns.detect { |c| c.name == "default_int" }
260
+ one = columns.detect { |c| c.name == "one_int" }
261
+ four = columns.detect { |c| c.name == "four_int" }
262
+ eight = columns.detect { |c| c.name == "eight_int" }
263
+ eleven = columns.detect { |c| c.name == "eleven_int" }
264
+
265
+ if current_adapter?(:PostgreSQLAdapter)
266
+ assert_equal 'integer', default.sql_type
267
+ assert_equal 'smallint', one.sql_type
268
+ assert_equal 'integer', four.sql_type
269
+ assert_equal 'bigint', eight.sql_type
270
+ assert_equal 'integer', eleven.sql_type
271
+ elsif current_adapter?(:MysqlAdapter)
272
+ assert_match 'int(11)', default.sql_type
273
+ assert_match 'tinyint', one.sql_type
274
+ assert_match 'int', four.sql_type
275
+ assert_match 'bigint', eight.sql_type
276
+ assert_match 'int(11)', eleven.sql_type
277
+ elsif current_adapter?(:OracleAdapter)
278
+ assert_equal 'NUMBER(38)', default.sql_type
279
+ assert_equal 'NUMBER(1)', one.sql_type
280
+ assert_equal 'NUMBER(4)', four.sql_type
281
+ assert_equal 'NUMBER(8)', eight.sql_type
282
+ end
283
+ ensure
284
+ Person.connection.drop_table :testings rescue nil
285
+ end
286
+
287
+ def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
288
+ ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
289
+
290
+ Person.connection.create_table :testings do |t|
291
+ t.column :foo, :string
292
+ end
293
+
294
+ assert_equal %w(foo testings_id), Person.connection.columns(:testings).map { |c| c.name }.sort
295
+ ensure
296
+ Person.connection.drop_table :testings rescue nil
297
+ ActiveRecord::Base.primary_key_prefix_type = nil
298
+ end
299
+
300
+ def test_create_table_with_primary_key_prefix_as_table_name
301
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
302
+
303
+ Person.connection.create_table :testings do |t|
304
+ t.column :foo, :string
305
+ end
306
+
307
+ assert_equal %w(foo testingsid), Person.connection.columns(:testings).map { |c| c.name }.sort
308
+ ensure
309
+ Person.connection.drop_table :testings rescue nil
310
+ ActiveRecord::Base.primary_key_prefix_type = nil
311
+ end
312
+
313
+ def test_create_table_with_force_true_does_not_drop_nonexisting_table
314
+ if Person.connection.table_exists?(:testings2)
315
+ Person.connection.drop_table :testings2
316
+ end
317
+
318
+ # using a copy as we need the drop_table method to
319
+ # continue to work for the ensure block of the test
320
+ temp_conn = Person.connection.dup
321
+ temp_conn.expects(:drop_table).never
322
+ temp_conn.create_table :testings2, :force => true do |t|
323
+ t.column :foo, :string
324
+ end
325
+ ensure
326
+ Person.connection.drop_table :testings2 rescue nil
327
+ end
328
+
329
+ def test_create_table_with_timestamps_should_create_datetime_columns
330
+ table_name = :testings
331
+
332
+ Person.connection.create_table table_name do |t|
333
+ t.timestamps
334
+ end
335
+ created_columns = Person.connection.columns(table_name)
336
+
337
+ created_at_column = created_columns.detect {|c| c.name == 'created_at' }
338
+ updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
339
+
340
+ assert created_at_column.null
341
+ assert updated_at_column.null
342
+ ensure
343
+ Person.connection.drop_table table_name rescue nil
344
+ end
345
+
346
+ def test_create_table_with_timestamps_should_create_datetime_columns_with_options
347
+ table_name = :testings
348
+
349
+ Person.connection.create_table table_name do |t|
350
+ t.timestamps :null => false
351
+ end
352
+ created_columns = Person.connection.columns(table_name)
353
+
354
+ created_at_column = created_columns.detect {|c| c.name == 'created_at' }
355
+ updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
356
+
357
+ assert !created_at_column.null
358
+ assert !updated_at_column.null
359
+ ensure
360
+ Person.connection.drop_table table_name rescue nil
361
+ end
362
+
363
+ # Sybase, and SQLite3 will not allow you to add a NOT NULL
364
+ # column to a table without a default value.
365
+ unless current_adapter?(:SybaseAdapter, :SQLiteAdapter, :IBM_DBAdapter)
366
+ def test_add_column_not_null_without_default
367
+ Person.connection.create_table :testings do |t|
368
+ t.column :foo, :string
369
+ end
370
+ Person.connection.add_column :testings, :bar, :string, :null => false
371
+
372
+ assert_raise(ActiveRecord::StatementInvalid) do
373
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
374
+ end
375
+ ensure
376
+ Person.connection.drop_table :testings rescue nil
377
+ end
378
+ end
379
+
380
+ def test_add_column_not_null_with_default
381
+ Person.connection.create_table :testings do |t|
382
+ t.column :foo, :string
383
+ end
384
+
385
+ con = Person.connection
386
+ Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
387
+ Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
388
+ Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
389
+ assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
390
+
391
+ assert_raise(ActiveRecord::StatementInvalid) do
392
+ unless current_adapter?(:OpenBaseAdapter)
393
+ 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)"
394
+ else
395
+ 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)",
396
+ "Testing Insert","id",2)
397
+ end
398
+ end
399
+ ensure
400
+ Person.connection.drop_table :testings rescue nil
401
+ end
402
+
403
+ # We specifically do a manual INSERT here, and then test only the SELECT
404
+ # functionality. This allows us to more easily catch INSERT being broken,
405
+ # but SELECT actually working fine.
406
+ def test_native_decimal_insert_manual_vs_automatic
407
+ correct_value = '0012345678901234567890.0123456789'.to_d
408
+
409
+ Person.delete_all
410
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
411
+ Person.reset_column_information
412
+
413
+ # Do a manual insertion
414
+ if current_adapter?(:OracleAdapter)
415
+ Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
416
+ elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
417
+ Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')"
418
+ else
419
+ Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
420
+ end
421
+
422
+ # SELECT
423
+ row = Person.find(:first)
424
+ assert_kind_of BigDecimal, row.wealth
425
+
426
+ # If this assert fails, that means the SELECT is broken!
427
+ unless current_adapter?(:SQLite3Adapter)
428
+ assert_equal correct_value, row.wealth
429
+ end
430
+
431
+ # Reset to old state
432
+ Person.delete_all
433
+
434
+ # Now use the Rails insertion
435
+ assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
436
+
437
+ # SELECT
438
+ row = Person.find(:first)
439
+ assert_kind_of BigDecimal, row.wealth
440
+
441
+ # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
442
+ unless current_adapter?(:SQLite3Adapter)
443
+ assert_equal correct_value, row.wealth
444
+ end
445
+
446
+ # Reset to old state
447
+ Person.connection.del_column "people", "wealth" rescue nil
448
+ Person.reset_column_information
449
+ end
450
+
451
+ def test_add_column_with_precision_and_scale
452
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
453
+ Person.reset_column_information
454
+
455
+ wealth_column = Person.columns_hash['wealth']
456
+ assert_equal 9, wealth_column.precision
457
+ assert_equal 7, wealth_column.scale
458
+ end
459
+
460
+ def test_native_types
461
+ Person.delete_all
462
+ Person.connection.add_column "people", "last_name", :string
463
+ Person.connection.add_column "people", "bio", :text
464
+ Person.connection.add_column "people", "age", :integer
465
+ Person.connection.add_column "people", "height", :float
466
+ Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
467
+ Person.connection.add_column "people", "birthday", :datetime
468
+ Person.connection.add_column "people", "favorite_day", :date
469
+ Person.connection.add_column "people", "moment_of_truth", :datetime
470
+ Person.connection.add_column "people", "male", :boolean
471
+ Person.reset_column_information
472
+
473
+ assert_nothing_raised do
474
+ Person.create :first_name => 'bob', :last_name => 'bobsen',
475
+ :bio => "I was born ....", :age => 18, :height => 1.78,
476
+ :wealth => BigDecimal.new("12345678901234567890.0123456789"),
477
+ :birthday => 18.years.ago, :favorite_day => 10.days.ago,
478
+ :moment_of_truth => "1782-10-10 21:40:18", :male => true
479
+ end
480
+
481
+ bob = Person.find(:first)
482
+ assert_equal 'bob', bob.first_name
483
+ assert_equal 'bobsen', bob.last_name
484
+ assert_equal "I was born ....", bob.bio
485
+ assert_equal 18, bob.age
486
+
487
+ # Test for 30 significent digits (beyond the 16 of float), 10 of them
488
+ # after the decimal place.
489
+
490
+ unless current_adapter?(:SQLite3Adapter)
491
+ assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
492
+ end
493
+
494
+ assert_equal true, bob.male?
495
+
496
+ assert_equal String, bob.first_name.class
497
+ assert_equal String, bob.last_name.class
498
+ assert_equal String, bob.bio.class
499
+ assert_equal Fixnum, bob.age.class
500
+ assert_equal Time, bob.birthday.class
501
+
502
+ if current_adapter?(:OracleAdapter, :SybaseAdapter)
503
+ # Sybase, and Oracle don't differentiate between date/time
504
+ assert_equal Time, bob.favorite_day.class
505
+ else
506
+ assert_equal Date, bob.favorite_day.class
507
+ end
508
+
509
+ # Test DateTime column and defaults, including timezone.
510
+ # FIXME: moment of truth may be Time on 64-bit platforms.
511
+ if bob.moment_of_truth.is_a?(DateTime)
512
+
513
+ with_env_tz 'US/Eastern' do
514
+ assert_equal DateTime.local_offset, bob.moment_of_truth.offset
515
+ assert_not_equal 0, bob.moment_of_truth.offset
516
+ assert_not_equal "Z", bob.moment_of_truth.zone
517
+ # US/Eastern is -5 hours from GMT
518
+ assert_equal Rational(-5, 24), bob.moment_of_truth.offset
519
+ assert_match /\A-05:?00\Z/, bob.moment_of_truth.zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM
520
+ assert_equal DateTime::ITALY, bob.moment_of_truth.start
521
+ end
522
+ end
523
+
524
+ assert_equal TrueClass, bob.male?.class
525
+ assert_kind_of BigDecimal, bob.wealth
526
+ end
527
+
528
+ if current_adapter?(:MysqlAdapter)
529
+ def test_unabstracted_database_dependent_types
530
+ Person.delete_all
531
+
532
+ ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint
533
+ Person.reset_column_information
534
+ assert_match /tinyint/, Person.columns_hash['intelligence_quotient'].sql_type
535
+ ensure
536
+ ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil
537
+ end
538
+ end
539
+
540
+ def test_add_remove_single_field_using_string_arguments
541
+ assert !Person.column_methods_hash.include?(:last_name)
542
+
543
+ ActiveRecord::Migration.add_column 'people', 'last_name', :string
544
+
545
+ Person.reset_column_information
546
+ assert Person.column_methods_hash.include?(:last_name)
547
+
548
+ ActiveRecord::Migration.remove_column 'people', 'last_name'
549
+
550
+ Person.reset_column_information
551
+ assert !Person.column_methods_hash.include?(:last_name)
552
+ end
553
+
554
+ def test_add_remove_single_field_using_symbol_arguments
555
+ assert !Person.column_methods_hash.include?(:last_name)
556
+
557
+ ActiveRecord::Migration.add_column :people, :last_name, :string
558
+
559
+ Person.reset_column_information
560
+ assert Person.column_methods_hash.include?(:last_name)
561
+
562
+ ActiveRecord::Migration.remove_column :people, :last_name
563
+
564
+ Person.reset_column_information
565
+ assert !Person.column_methods_hash.include?(:last_name)
566
+ end
567
+
568
+ if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
569
+ def test_add_rename
570
+ Person.delete_all
571
+
572
+ begin
573
+ Person.connection.add_column "people", "girlfriend", :string
574
+ Person.reset_column_information
575
+ Person.create :girlfriend => 'bobette'
576
+
577
+ Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
578
+
579
+ Person.reset_column_information
580
+ bob = Person.find(:first)
581
+
582
+ assert_equal "bobette", bob.exgirlfriend
583
+ ensure
584
+ Person.connection.remove_column("people", "girlfriend") rescue nil
585
+ Person.connection.remove_column("people", "exgirlfriend") rescue nil
586
+ end
587
+
588
+ end
589
+
590
+ def test_rename_column_using_symbol_arguments
591
+ begin
592
+ names_before = Person.find(:all).map(&:first_name)
593
+ Person.connection.rename_column :people, :first_name, :nick_name
594
+ Person.reset_column_information
595
+ assert Person.column_names.include?("nick_name")
596
+ assert_equal names_before, Person.find(:all).map(&:nick_name)
597
+ ensure
598
+ Person.connection.remove_column("people","nick_name")
599
+ Person.connection.add_column("people","first_name", :string)
600
+ end
601
+ end
602
+
603
+ def test_rename_column
604
+ begin
605
+ names_before = Person.find(:all).map(&:first_name)
606
+ Person.connection.rename_column "people", "first_name", "nick_name"
607
+ Person.reset_column_information
608
+ assert Person.column_names.include?("nick_name")
609
+ assert_equal names_before, Person.find(:all).map(&:nick_name)
610
+ ensure
611
+ Person.connection.remove_column("people","nick_name")
612
+ Person.connection.add_column("people","first_name", :string)
613
+ end
614
+ end
615
+
616
+ def test_rename_column_preserves_default_value_not_null
617
+ begin
618
+ default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
619
+ assert_equal 70000, default_before
620
+ Developer.connection.rename_column "developers", "salary", "anual_salary"
621
+ Developer.reset_column_information
622
+ assert Developer.column_names.include?("anual_salary")
623
+ default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
624
+ assert_equal 70000, default_after
625
+ ensure
626
+ Developer.connection.rename_column "developers", "anual_salary", "salary"
627
+ Developer.reset_column_information
628
+ end
629
+ end
630
+
631
+ def test_rename_nonexistent_column
632
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
633
+ table.column :hat_name, :string, :default => nil
634
+ end
635
+ exception = if current_adapter?(:PostgreSQLAdapter)
636
+ ActiveRecord::StatementInvalid
637
+ else
638
+ ActiveRecord::ActiveRecordError
639
+ end
640
+ assert_raise(exception) do
641
+ Person.connection.rename_column "hats", "nonexistent", "should_fail"
642
+ end
643
+ ensure
644
+ ActiveRecord::Base.connection.drop_table(:hats)
645
+ end
646
+
647
+ def test_rename_column_with_sql_reserved_word
648
+ begin
649
+ assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
650
+ Person.reset_column_information
651
+ assert Person.column_names.include?("group")
652
+ ensure
653
+ Person.connection.remove_column("people", "group") rescue nil
654
+ Person.connection.add_column("people", "first_name", :string) rescue nil
655
+ end
656
+ end
657
+ end
658
+
659
+ unless (current_adapter?(:IBM_DBAdapter)) #Cannot alter a object when there is another object depending on it
660
+ def test_rename_column_with_an_index
661
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
662
+ table.column :hat_name, :string, :limit => 100
663
+ table.column :hat_size, :integer
664
+ end
665
+ Person.connection.add_index :hats, :hat_name
666
+ assert_nothing_raised do
667
+ Person.connection.rename_column "hats", "hat_name", "name"
668
+ end
669
+ ensure
670
+ ActiveRecord::Base.connection.drop_table(:hats)
671
+ end
672
+ end
673
+
674
+ def test_remove_column_with_index
675
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
676
+ table.column :hat_name, :string, :limit => 100
677
+ table.column :hat_size, :integer
678
+ end
679
+ ActiveRecord::Base.connection.add_index "hats", "hat_size"
680
+
681
+ assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
682
+ ensure
683
+ ActiveRecord::Base.connection.drop_table(:hats)
684
+ end
685
+
686
+ unless (current_adapter?(:IBM_DBAdapter)) #Cannot alter a object when there is another object depending on it
687
+ def test_remove_column_with_multi_column_index
688
+ ActiveRecord::Base.connection.create_table(:hats) do |table|
689
+ table.column :hat_name, :string, :limit => 100
690
+ table.column :hat_size, :integer
691
+ table.column :hat_style, :string, :limit => 100
692
+ end
693
+ ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
694
+
695
+ assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
696
+ ensure
697
+ ActiveRecord::Base.connection.drop_table(:hats)
698
+ end
699
+ end
700
+
701
+ unless current_adapter?(:IBM_DBAdapter) #incompatible types changes
702
+ def test_change_type_of_not_null_column
703
+ assert_nothing_raised do
704
+ Topic.connection.change_column "topics", "written_on", :datetime, :null => false
705
+ Topic.reset_column_information
706
+
707
+ Topic.connection.change_column "topics", "written_on", :datetime, :null => false
708
+ Topic.reset_column_information
709
+ end
710
+ end
711
+ end
712
+
713
+ def test_rename_table
714
+ begin
715
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
716
+ t.column :url, :string
717
+ end
718
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
719
+
720
+ # Using explicit id in insert for compatibility across all databases
721
+ con = ActiveRecord::Base.connection
722
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
723
+ 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')" }
724
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
725
+
726
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
727
+
728
+ ensure
729
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
730
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
731
+ end
732
+ end
733
+
734
+ def test_change_column_nullability
735
+ Person.delete_all
736
+ Person.connection.add_column "people", "funny", :boolean
737
+ Person.reset_column_information
738
+ assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
739
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types changes
740
+ Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true
741
+ Person.reset_column_information
742
+ assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
743
+ Person.connection.change_column "people", "funny", :boolean, :null => true
744
+ Person.reset_column_information
745
+ assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
746
+ end
747
+ end
748
+
749
+ def test_rename_table_with_an_index
750
+ begin
751
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
752
+ t.column :url, :string
753
+ end
754
+ ActiveRecord::Base.connection.add_index :octopuses, :url
755
+
756
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
757
+
758
+ # Using explicit id in insert for compatibility across all databases
759
+ con = ActiveRecord::Base.connection
760
+ con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
761
+ 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')" }
762
+ con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
763
+
764
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
765
+ assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
766
+ ensure
767
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
768
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
769
+ end
770
+ end
771
+
772
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types changes
773
+ def test_change_column
774
+ Person.connection.add_column 'people', 'age', :integer
775
+ old_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
776
+ assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
777
+
778
+ assert_nothing_raised { Person.connection.change_column "people", "age", :string }
779
+
780
+ new_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
781
+ assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
782
+ assert new_columns.find { |c| c.name == 'age' and c.type == :string }
783
+
784
+ old_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
785
+ assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
786
+ assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
787
+ new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
788
+ assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
789
+ assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
790
+ assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
791
+ end
792
+ end
793
+
794
+ def test_change_column_with_nil_default
795
+ Person.connection.add_column "people", "contributor", :boolean, :default => true
796
+ Person.reset_column_information
797
+ assert Person.new.contributor?
798
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types changes
799
+ assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
800
+ Person.reset_column_information
801
+ assert !Person.new.contributor?
802
+ assert_nil Person.new.contributor
803
+ end
804
+ ensure
805
+ Person.connection.remove_column("people", "contributor") rescue nil
806
+ end
807
+
808
+ def test_change_column_with_new_default
809
+ Person.connection.add_column "people", "administrator", :boolean, :default => true
810
+ Person.reset_column_information
811
+ assert Person.new.administrator?
812
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types changes
813
+ assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
814
+ Person.reset_column_information
815
+ assert !Person.new.administrator?
816
+ end
817
+ ensure
818
+ Person.connection.remove_column("people", "administrator") rescue nil
819
+ end
820
+
821
+ def test_change_column_default
822
+ Person.connection.change_column_default "people", "first_name", "Tester"
823
+ Person.reset_column_information
824
+ assert_equal "Tester", Person.new.first_name
825
+ end
826
+
827
+ def test_change_column_quotes_column_names
828
+ Person.connection.create_table :testings do |t|
829
+ t.column :select, :string
830
+ end
831
+ unless current_adapter?(:IBM_DBAdapter) # altering a string column to smaller size
832
+ assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 }
833
+ end
834
+
835
+ assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
836
+ ensure
837
+ Person.connection.drop_table :testings rescue nil
838
+ end
839
+
840
+ def test_keeping_default_and_notnull_constaint_on_change
841
+ Person.connection.create_table :testings do |t|
842
+ t.column :title, :string
843
+ end
844
+ person_klass = Class.new(Person)
845
+ person_klass.set_table_name 'testings'
846
+
847
+ person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
848
+ person_klass.reset_column_information
849
+ assert_equal 99, person_klass.columns_hash["wealth"].default
850
+ assert_equal false, person_klass.columns_hash["wealth"].null
851
+ assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
852
+
853
+ # change column default to see that column doesn't lose its not null definition
854
+ person_klass.connection.change_column_default "testings", "wealth", 100
855
+ person_klass.reset_column_information
856
+ assert_equal 100, person_klass.columns_hash["wealth"].default
857
+ assert_equal false, person_klass.columns_hash["wealth"].null
858
+
859
+ # rename column to see that column doesn't lose its not null and/or default definition
860
+ if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
861
+ person_klass.connection.rename_column "testings", "wealth", "money"
862
+ person_klass.reset_column_information
863
+ assert_nil person_klass.columns_hash["wealth"]
864
+ assert_equal 100, person_klass.columns_hash["money"].default
865
+ assert_equal false, person_klass.columns_hash["money"].null
866
+ end
867
+
868
+ # change column
869
+ unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
870
+ person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
871
+ person_klass.reset_column_information
872
+ assert_equal 1000, person_klass.columns_hash["money"].default
873
+ assert_equal false, person_klass.columns_hash["money"].null
874
+ else
875
+ person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 15, :scale => 1,:null => false, :default => 1000
876
+ person_klass.reset_column_information
877
+ assert_equal 1000, person_klass.columns_hash["wealth"].default
878
+ assert_equal false, person_klass.columns_hash["wealth"].null
879
+ end
880
+
881
+ # change column, make it nullable and clear default
882
+ unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
883
+ person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
884
+ person_klass.reset_column_information
885
+ assert_nil person_klass.columns_hash["money"].default
886
+ assert_equal true, person_klass.columns_hash["money"].null
887
+ else
888
+ person_klass.connection.change_column "testings", "wealth", :decimal, :precision => 20, :scale => 2, :null => true, :default => nil
889
+ person_klass.reset_column_information
890
+ assert_nil person_klass.columns_hash["wealth"].default
891
+ assert_equal true, person_klass.columns_hash["wealth"].null
892
+ end
893
+
894
+ # change_column_null, make it not nullable and set null values to a default value
895
+ unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
896
+ person_klass.connection.execute('UPDATE testings SET money = NULL')
897
+ person_klass.connection.change_column_null "testings", "money", false, 2000
898
+ person_klass.reset_column_information
899
+ assert_nil person_klass.columns_hash["money"].default
900
+ assert_equal false, person_klass.columns_hash["money"].null
901
+ assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
902
+ else
903
+ # Trying to set the value of the column wealth to NULL and
904
+ # in the next statement a not null constraint is being applied which is wrong.
905
+ #person_klass.connection.execute('UPDATE testings SET wealth = NULL')
906
+ person_klass.connection.change_column_null "testings", "wealth", false, 2000
907
+ person_klass.reset_column_information
908
+ assert_equal false, person_klass.columns_hash["wealth"].null
909
+ assert_equal 2000, person_klass.columns_hash["wealth"].default
910
+ end
911
+ ensure
912
+ Person.connection.drop_table :testings rescue nil
913
+ end
914
+
915
+ def test_change_column_default_to_null
916
+ if current_adapter?(:IBM_DBAdapter)
917
+ #Ensure that first_name had some default value else an error is thrown saying operation not valid
918
+ Person.connection.change_column_default "people", "first_name", "foo"
919
+ end
920
+ Person.connection.change_column_default "people", "first_name", nil
921
+ Person.reset_column_information
922
+ assert_nil Person.new.first_name
923
+ end
924
+
925
+ def test_add_table
926
+ assert !Reminder.table_exists?
927
+
928
+ WeNeedReminders.up
929
+
930
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
931
+ assert_equal "hello world", Reminder.find(:first).content
932
+
933
+ WeNeedReminders.down
934
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
935
+ end
936
+
937
+ def test_add_table_with_decimals
938
+ Person.connection.drop_table :big_numbers rescue nil
939
+
940
+ assert !BigNumber.table_exists?
941
+ GiveMeBigNumbers.up
942
+
943
+ assert BigNumber.create(
944
+ :bank_balance => 1586.43,
945
+ :big_bank_balance => BigDecimal("1000234000567.95"),
946
+ :world_population => 6000000000,
947
+ :my_house_population => 3,
948
+ :value_of_e => BigDecimal("2.7182818284590452353602875")
949
+ )
950
+
951
+ b = BigNumber.find(:first)
952
+ assert_not_nil b
953
+
954
+ assert_not_nil b.bank_balance
955
+ assert_not_nil b.big_bank_balance
956
+ assert_not_nil b.world_population
957
+ assert_not_nil b.my_house_population
958
+ assert_not_nil b.value_of_e
959
+
960
+ # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
961
+ # is_a?(Bignum)
962
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types retrieved
963
+ assert_kind_of Integer, b.world_population
964
+ else
965
+ assert_kind_of BigDecimal, b.world_population
966
+ end
967
+ assert_equal 6000000000, b.world_population
968
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types retrieved
969
+ assert_kind_of Fixnum, b.my_house_population
970
+ else
971
+ assert_kind_of BigDecimal, b.my_house_population
972
+ end
973
+ assert_equal 3, b.my_house_population
974
+ assert_kind_of BigDecimal, b.bank_balance
975
+ assert_equal BigDecimal("1586.43"), b.bank_balance
976
+ assert_kind_of BigDecimal, b.big_bank_balance
977
+ assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
978
+
979
+ # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
980
+ # precision/scale explicitly left out. By the SQL standard, numbers
981
+ # assigned to this field should be truncated but that's seldom respected.
982
+ if current_adapter?(:PostgreSQLAdapter, :SQLite2Adapter)
983
+ # - PostgreSQL changes the SQL spec on columns declared simply as
984
+ # "decimal" to something more useful: instead of being given a scale
985
+ # of 0, they take on the compile-time limit for precision and scale,
986
+ # so the following should succeed unless you have used really wacky
987
+ # compilation options
988
+ # - SQLite2 has the default behavior of preserving all data sent in,
989
+ # so this happens there too
990
+ assert_kind_of BigDecimal, b.value_of_e
991
+ assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
992
+ elsif current_adapter?(:SQLiteAdapter)
993
+ # - SQLite3 stores a float, in violation of SQL
994
+ assert_kind_of BigDecimal, b.value_of_e
995
+ assert_equal BigDecimal("2.71828182845905"), b.value_of_e
996
+ else
997
+ # - SQL standard is an integer
998
+ unless current_adapter?(:IBM_DBAdapter) # incompatible types retrieved
999
+ assert_kind_of Fixnum, b.value_of_e
1000
+ else
1001
+ assert_kind_of BigDecimal, b.value_of_e
1002
+ end
1003
+ assert_equal 2, b.value_of_e
1004
+ end
1005
+
1006
+ GiveMeBigNumbers.down
1007
+ assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
1008
+ end
1009
+
1010
+ def test_migrator
1011
+ assert !Person.column_methods_hash.include?(:last_name)
1012
+ assert !Reminder.table_exists?
1013
+
1014
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1015
+
1016
+ assert_equal 3, ActiveRecord::Migrator.current_version
1017
+ Person.reset_column_information
1018
+ assert Person.column_methods_hash.include?(:last_name)
1019
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1020
+ assert_equal "hello world", Reminder.find(:first).content
1021
+
1022
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
1023
+
1024
+ assert_equal 0, ActiveRecord::Migrator.current_version
1025
+ Person.reset_column_information
1026
+ assert !Person.column_methods_hash.include?(:last_name)
1027
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1028
+ end
1029
+
1030
+ def test_migrator_one_up
1031
+ assert !Person.column_methods_hash.include?(:last_name)
1032
+ assert !Reminder.table_exists?
1033
+
1034
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1035
+
1036
+ Person.reset_column_information
1037
+ assert Person.column_methods_hash.include?(:last_name)
1038
+ assert !Reminder.table_exists?
1039
+
1040
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2)
1041
+
1042
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1043
+ assert_equal "hello world", Reminder.find(:first).content
1044
+ end
1045
+
1046
+ def test_migrator_one_down
1047
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
1048
+
1049
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
1050
+
1051
+ Person.reset_column_information
1052
+ assert Person.column_methods_hash.include?(:last_name)
1053
+ assert !Reminder.table_exists?
1054
+ end
1055
+
1056
+ def test_migrator_one_up_one_down
1057
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1058
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1059
+
1060
+ assert !Person.column_methods_hash.include?(:last_name)
1061
+ assert !Reminder.table_exists?
1062
+ end
1063
+
1064
+ def test_migrator_double_up
1065
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1066
+ ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1067
+ assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) }
1068
+ assert_equal(1, ActiveRecord::Migrator.current_version)
1069
+ end
1070
+
1071
+ def test_migrator_double_down
1072
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1073
+ ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1)
1074
+ ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1)
1075
+ assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) }
1076
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1077
+ end
1078
+
1079
+ if ActiveRecord::Base.connection.supports_ddl_transactions?
1080
+ def test_migrator_one_up_with_exception_and_rollback
1081
+ assert !Person.column_methods_hash.include?(:last_name)
1082
+
1083
+ e = assert_raise(StandardError) do
1084
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
1085
+ end
1086
+
1087
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
1088
+
1089
+ Person.reset_column_information
1090
+ assert !Person.column_methods_hash.include?(:last_name)
1091
+ end
1092
+ end
1093
+
1094
+ def test_finds_migrations
1095
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
1096
+
1097
+ [[1, 'PeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i|
1098
+ assert_equal migrations[i].version, pair.first
1099
+ assert_equal migrations[i].name, pair.last
1100
+ end
1101
+ end
1102
+
1103
+ def test_finds_pending_migrations
1104
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
1105
+ migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
1106
+ assert_equal 1, migrations.size
1107
+ assert_equal migrations[0].version, 3
1108
+ assert_equal migrations[0].name, 'InnocentJointable'
1109
+ end
1110
+
1111
+ def test_only_loads_pending_migrations
1112
+ # migrate up to 1
1113
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1114
+
1115
+ # now unload the migrations that have been defined
1116
+ PeopleHaveLastNames.unloadable
1117
+ ActiveSupport::Dependencies.remove_unloadable_constants!
1118
+
1119
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
1120
+
1121
+ assert !defined? PeopleHaveLastNames
1122
+
1123
+ %w(WeNeedReminders, InnocentJointable).each do |migration|
1124
+ assert defined? migration
1125
+ end
1126
+
1127
+ ensure
1128
+ load(MIGRATIONS_ROOT + "/valid/1_people_have_last_names.rb")
1129
+ end
1130
+
1131
+ def test_migrator_interleaved_migrations
1132
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
1133
+
1134
+ assert_nothing_raised do
1135
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2")
1136
+ end
1137
+
1138
+ Person.reset_column_information
1139
+ assert Person.column_methods_hash.include?(:last_name)
1140
+
1141
+ assert_nothing_raised do
1142
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/interleaved/pass_3")
1143
+ end
1144
+ end
1145
+
1146
+ def test_migrator_db_has_no_schema_migrations_table
1147
+ ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;")
1148
+ assert_nothing_raised do
1149
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1)
1150
+ end
1151
+ end
1152
+
1153
+ def test_migrator_verbosity
1154
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1155
+ assert PeopleHaveLastNames.message_count > 0
1156
+ PeopleHaveLastNames.message_count = 0
1157
+
1158
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1159
+ assert PeopleHaveLastNames.message_count > 0
1160
+ PeopleHaveLastNames.message_count = 0
1161
+ end
1162
+
1163
+ def test_migrator_verbosity_off
1164
+ PeopleHaveLastNames.verbose = false
1165
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1166
+ assert PeopleHaveLastNames.message_count.zero?
1167
+ ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0)
1168
+ assert PeopleHaveLastNames.message_count.zero?
1169
+ end
1170
+
1171
+ def test_migrator_going_down_due_to_version_target
1172
+ ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
1173
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0)
1174
+
1175
+ assert !Person.column_methods_hash.include?(:last_name)
1176
+ assert !Reminder.table_exists?
1177
+
1178
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1179
+
1180
+ Person.reset_column_information
1181
+ assert Person.column_methods_hash.include?(:last_name)
1182
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1183
+ assert_equal "hello world", Reminder.find(:first).content
1184
+ end
1185
+
1186
+ def test_migrator_rollback
1187
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1188
+ assert_equal(3, ActiveRecord::Migrator.current_version)
1189
+
1190
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1191
+ assert_equal(2, ActiveRecord::Migrator.current_version)
1192
+
1193
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1194
+ assert_equal(1, ActiveRecord::Migrator.current_version)
1195
+
1196
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1197
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1198
+
1199
+ ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1200
+ assert_equal(0, ActiveRecord::Migrator.current_version)
1201
+ end
1202
+
1203
+ def test_schema_migrations_table_name
1204
+ ActiveRecord::Base.table_name_prefix = "prefix_"
1205
+ ActiveRecord::Base.table_name_suffix = "_suffix"
1206
+ Reminder.reset_table_name
1207
+ assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name
1208
+ ActiveRecord::Base.table_name_prefix = ""
1209
+ ActiveRecord::Base.table_name_suffix = ""
1210
+ Reminder.reset_table_name
1211
+ assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name
1212
+ ensure
1213
+ ActiveRecord::Base.table_name_prefix = ""
1214
+ ActiveRecord::Base.table_name_suffix = ""
1215
+ end
1216
+
1217
+ def test_proper_table_name
1218
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
1219
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
1220
+ assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
1221
+ Reminder.reset_table_name
1222
+ assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
1223
+
1224
+ # Use the model's own prefix/suffix if a model is given
1225
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
1226
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
1227
+ Reminder.table_name_prefix = 'prefix_'
1228
+ Reminder.table_name_suffix = '_suffix'
1229
+ Reminder.reset_table_name
1230
+ assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
1231
+ Reminder.table_name_prefix = ''
1232
+ Reminder.table_name_suffix = ''
1233
+ Reminder.reset_table_name
1234
+
1235
+ # Use AR::Base's prefix/suffix if string or symbol is given
1236
+ ActiveRecord::Base.table_name_prefix = "prefix_"
1237
+ ActiveRecord::Base.table_name_suffix = "_suffix"
1238
+ Reminder.reset_table_name
1239
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
1240
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
1241
+ ActiveRecord::Base.table_name_prefix = ""
1242
+ ActiveRecord::Base.table_name_suffix = ""
1243
+ Reminder.reset_table_name
1244
+ end
1245
+
1246
+ def test_add_drop_table_with_prefix_and_suffix
1247
+ assert !Reminder.table_exists?
1248
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
1249
+ ActiveRecord::Base.table_name_suffix = '_suffix'
1250
+ Reminder.reset_table_name
1251
+ Reminder.reset_sequence_name
1252
+ WeNeedReminders.up
1253
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1254
+ assert_equal "hello world", Reminder.find(:first).content
1255
+
1256
+ WeNeedReminders.down
1257
+ assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
1258
+ ensure
1259
+ ActiveRecord::Base.table_name_prefix = ''
1260
+ ActiveRecord::Base.table_name_suffix = ''
1261
+ Reminder.reset_table_name
1262
+ Reminder.reset_sequence_name
1263
+ end
1264
+
1265
+ def test_create_table_with_binary_column
1266
+ Person.connection.drop_table :binary_testings rescue nil
1267
+
1268
+ assert_nothing_raised {
1269
+ Person.connection.create_table :binary_testings do |t|
1270
+ t.column "data", :binary, :null => false
1271
+ end
1272
+ }
1273
+
1274
+ columns = Person.connection.columns(:binary_testings)
1275
+ data_column = columns.detect { |c| c.name == "data" }
1276
+
1277
+ if current_adapter?(:MysqlAdapter)
1278
+ assert_equal '', data_column.default
1279
+ else
1280
+ assert_nil data_column.default
1281
+ end
1282
+
1283
+ Person.connection.drop_table :binary_testings rescue nil
1284
+ end
1285
+
1286
+ def test_migrator_with_duplicates
1287
+ assert_raise(ActiveRecord::DuplicateMigrationVersionError) do
1288
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil)
1289
+ end
1290
+ end
1291
+
1292
+ def test_migrator_with_duplicate_names
1293
+ assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
1294
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil)
1295
+ end
1296
+ end
1297
+
1298
+ def test_migrator_with_missing_version_numbers
1299
+ assert_raise(ActiveRecord::UnknownMigrationVersionError) do
1300
+ ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500)
1301
+ end
1302
+ end
1303
+
1304
+ def test_create_table_with_custom_sequence_name
1305
+ return unless current_adapter? :OracleAdapter
1306
+
1307
+ # table name is 29 chars, the standard sequence name will
1308
+ # be 33 chars and fail
1309
+ assert_raise(ActiveRecord::StatementInvalid) do
1310
+ begin
1311
+ Person.connection.create_table :table_with_name_thats_just_ok do |t|
1312
+ t.column :foo, :string, :null => false
1313
+ end
1314
+ ensure
1315
+ Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
1316
+ end
1317
+ end
1318
+
1319
+ # should be all good w/ a custom sequence name
1320
+ assert_nothing_raised do
1321
+ begin
1322
+ Person.connection.create_table :table_with_name_thats_just_ok,
1323
+ :sequence_name => 'suitably_short_seq' do |t|
1324
+ t.column :foo, :string, :null => false
1325
+ end
1326
+
1327
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
1328
+
1329
+ ensure
1330
+ Person.connection.drop_table :table_with_name_thats_just_ok,
1331
+ :sequence_name => 'suitably_short_seq' rescue nil
1332
+ end
1333
+ end
1334
+
1335
+ # confirm the custom sequence got dropped
1336
+ assert_raise(ActiveRecord::StatementInvalid) do
1337
+ Person.connection.execute("select suitably_short_seq.nextval from dual")
1338
+ end
1339
+ end
1340
+
1341
+ protected
1342
+ def with_env_tz(new_tz = 'US/Eastern')
1343
+ old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1344
+ yield
1345
+ ensure
1346
+ old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1347
+ end
1348
+
1349
+ end
1350
+
1351
+ class SexyMigrationsTest < ActiveRecord::TestCase
1352
+ def test_references_column_type_adds_id
1353
+ with_new_table do |t|
1354
+ t.expects(:column).with('customer_id', :integer, {})
1355
+ t.references :customer
1356
+ end
1357
+ end
1358
+
1359
+ def test_references_column_type_with_polymorphic_adds_type
1360
+ with_new_table do |t|
1361
+ t.expects(:column).with('taggable_type', :string, {})
1362
+ t.expects(:column).with('taggable_id', :integer, {})
1363
+ t.references :taggable, :polymorphic => true
1364
+ end
1365
+ end
1366
+
1367
+ def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1368
+ with_new_table do |t|
1369
+ t.expects(:column).with('taggable_type', :string, {:null => false})
1370
+ t.expects(:column).with('taggable_id', :integer, {:null => false})
1371
+ t.references :taggable, :polymorphic => true, :null => false
1372
+ end
1373
+ end
1374
+
1375
+ def test_belongs_to_works_like_references
1376
+ with_new_table do |t|
1377
+ t.expects(:column).with('customer_id', :integer, {})
1378
+ t.belongs_to :customer
1379
+ end
1380
+ end
1381
+
1382
+ def test_timestamps_creates_updated_at_and_created_at
1383
+ with_new_table do |t|
1384
+ t.expects(:column).with(:created_at, :datetime, kind_of(Hash))
1385
+ t.expects(:column).with(:updated_at, :datetime, kind_of(Hash))
1386
+ t.timestamps
1387
+ end
1388
+ end
1389
+
1390
+ def test_integer_creates_integer_column
1391
+ with_new_table do |t|
1392
+ t.expects(:column).with(:foo, 'integer', {})
1393
+ t.expects(:column).with(:bar, 'integer', {})
1394
+ t.integer :foo, :bar
1395
+ end
1396
+ end
1397
+
1398
+ def test_string_creates_string_column
1399
+ with_new_table do |t|
1400
+ t.expects(:column).with(:foo, 'string', {})
1401
+ t.expects(:column).with(:bar, 'string', {})
1402
+ t.string :foo, :bar
1403
+ end
1404
+ end
1405
+
1406
+ protected
1407
+ def with_new_table
1408
+ Person.connection.create_table :delete_me, :force => true do |t|
1409
+ yield t
1410
+ end
1411
+ ensure
1412
+ Person.connection.drop_table :delete_me rescue nil
1413
+ end
1414
+
1415
+ end # SexyMigrationsTest
1416
+
1417
+ class ChangeTableMigrationsTest < ActiveRecord::TestCase
1418
+ def setup
1419
+ @connection = Person.connection
1420
+ @connection.create_table :delete_me, :force => true do |t|
1421
+ end
1422
+ end
1423
+
1424
+ def teardown
1425
+ Person.connection.drop_table :delete_me rescue nil
1426
+ end
1427
+
1428
+ def test_references_column_type_adds_id
1429
+ with_change_table do |t|
1430
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1431
+ t.references :customer
1432
+ end
1433
+ end
1434
+
1435
+ def test_remove_references_column_type_removes_id
1436
+ with_change_table do |t|
1437
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1438
+ t.remove_references :customer
1439
+ end
1440
+ end
1441
+
1442
+ def test_add_belongs_to_works_like_add_references
1443
+ with_change_table do |t|
1444
+ @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1445
+ t.belongs_to :customer
1446
+ end
1447
+ end
1448
+
1449
+ def test_remove_belongs_to_works_like_remove_references
1450
+ with_change_table do |t|
1451
+ @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1452
+ t.remove_belongs_to :customer
1453
+ end
1454
+ end
1455
+
1456
+ def test_references_column_type_with_polymorphic_adds_type
1457
+ with_change_table do |t|
1458
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1459
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1460
+ t.references :taggable, :polymorphic => true
1461
+ end
1462
+ end
1463
+
1464
+ def test_remove_references_column_type_with_polymorphic_removes_type
1465
+ with_change_table do |t|
1466
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1467
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1468
+ t.remove_references :taggable, :polymorphic => true
1469
+ end
1470
+ end
1471
+
1472
+ def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1473
+ with_change_table do |t|
1474
+ @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1475
+ @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1476
+ t.references :taggable, :polymorphic => true, :null => false
1477
+ end
1478
+ end
1479
+
1480
+ def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1481
+ with_change_table do |t|
1482
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1483
+ @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1484
+ t.remove_references :taggable, :polymorphic => true, :null => false
1485
+ end
1486
+ end
1487
+
1488
+ def test_timestamps_creates_updated_at_and_created_at
1489
+ with_change_table do |t|
1490
+ @connection.expects(:add_timestamps).with(:delete_me)
1491
+ t.timestamps
1492
+ end
1493
+ end
1494
+
1495
+ def test_remove_timestamps_creates_updated_at_and_created_at
1496
+ with_change_table do |t|
1497
+ @connection.expects(:remove_timestamps).with(:delete_me)
1498
+ t.remove_timestamps
1499
+ end
1500
+ end
1501
+
1502
+ def string_column
1503
+ if current_adapter?(:PostgreSQLAdapter)
1504
+ "character varying(255)"
1505
+ else
1506
+ 'varchar(255)'
1507
+ end
1508
+ end
1509
+
1510
+ def integer_column
1511
+ if current_adapter?(:MysqlAdapter)
1512
+ 'int(11)'
1513
+ else
1514
+ 'integer'
1515
+ end
1516
+ end
1517
+
1518
+ def test_integer_creates_integer_column
1519
+ with_change_table do |t|
1520
+ @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {})
1521
+ @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {})
1522
+ t.integer :foo, :bar
1523
+ end
1524
+ end
1525
+
1526
+ def test_string_creates_string_column
1527
+ with_change_table do |t|
1528
+ @connection.expects(:add_column).with(:delete_me, :foo, string_column, {})
1529
+ @connection.expects(:add_column).with(:delete_me, :bar, string_column, {})
1530
+ t.string :foo, :bar
1531
+ end
1532
+ end
1533
+
1534
+ def test_column_creates_column
1535
+ with_change_table do |t|
1536
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1537
+ t.column :bar, :integer
1538
+ end
1539
+ end
1540
+
1541
+ def test_column_creates_column_with_options
1542
+ with_change_table do |t|
1543
+ @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1544
+ t.column :bar, :integer, :null => false
1545
+ end
1546
+ end
1547
+
1548
+ def test_index_creates_index
1549
+ with_change_table do |t|
1550
+ @connection.expects(:add_index).with(:delete_me, :bar, {})
1551
+ t.index :bar
1552
+ end
1553
+ end
1554
+
1555
+ def test_index_creates_index_with_options
1556
+ with_change_table do |t|
1557
+ @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
1558
+ t.index :bar, :unique => true
1559
+ end
1560
+ end
1561
+
1562
+ def test_change_changes_column
1563
+ with_change_table do |t|
1564
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
1565
+ t.change :bar, :string
1566
+ end
1567
+ end
1568
+
1569
+ def test_change_changes_column_with_options
1570
+ with_change_table do |t|
1571
+ @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
1572
+ t.change :bar, :string, :null => true
1573
+ end
1574
+ end
1575
+
1576
+ def test_change_default_changes_column
1577
+ with_change_table do |t|
1578
+ @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
1579
+ t.change_default :bar, :string
1580
+ end
1581
+ end
1582
+
1583
+ def test_remove_drops_single_column
1584
+ with_change_table do |t|
1585
+ @connection.expects(:remove_column).with(:delete_me, [:bar])
1586
+ t.remove :bar
1587
+ end
1588
+ end
1589
+
1590
+ def test_remove_drops_multiple_columns
1591
+ with_change_table do |t|
1592
+ @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
1593
+ t.remove :bar, :baz
1594
+ end
1595
+ end
1596
+
1597
+ def test_remove_index_removes_index_with_options
1598
+ with_change_table do |t|
1599
+ @connection.expects(:remove_index).with(:delete_me, {:unique => true})
1600
+ t.remove_index :unique => true
1601
+ end
1602
+ end
1603
+
1604
+ def test_rename_renames_column
1605
+ with_change_table do |t|
1606
+ @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
1607
+ t.rename :bar, :baz
1608
+ end
1609
+ end
1610
+
1611
+ protected
1612
+ def with_change_table
1613
+ Person.connection.change_table :delete_me do |t|
1614
+ yield t
1615
+ end
1616
+ end
1617
+ end
1618
+ end