2 require 'bigdecimal/util'
4 require 'models/person'
6 require 'models/developer'
8 require MIGRATIONS_ROOT
+ "/valid/1_people_have_last_names"
9 require MIGRATIONS_ROOT
+ "/valid/2_we_need_reminders"
10 require MIGRATIONS_ROOT
+ "/decimal/1_give_me_big_numbers"
11 require MIGRATIONS_ROOT
+ "/interleaved/pass_3/2_i_raise_on_down"
13 if ActiveRecord
::Base.connection
.supports_migrations
?
14 class BigNumber
< ActiveRecord
::Base; end
16 class Reminder
< ActiveRecord
::Base; end
18 class ActiveRecord
::Migration
20 attr_accessor :message_count
22 self.message_count
||= 0
23 self.message_count
+= 1
28 class MigrationTest
< ActiveRecord
::TestCase
29 self.use_transactional_fixtures
= false
34 ActiveRecord
::Migration.verbose
= true
35 PeopleHaveLastNames
.message_count
= 0
39 ActiveRecord
::Base.connection
.initialize_schema_migrations_table
40 ActiveRecord
::Base.connection
.execute
"DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}"
42 %w(reminders people_reminders prefix_reminders_suffix
).each
do |table
|
43 Reminder
.connection
.drop_table(table
) rescue nil
45 Reminder
.reset_column_information
47 %w(last_name key bio age height wealth birthday favorite_day
48 moment_of_truth male administrator funny
).each
do |column
|
49 Person
.connection
.remove_column('people', column
) rescue nil
51 Person
.connection
.remove_column("people", "first_name") rescue nil
52 Person
.connection
.remove_column("people", "middle_name") rescue nil
53 Person
.connection
.add_column("people", "first_name", :string, :limit => 40)
54 Person
.reset_column_information
58 # Limit size of last_name and key columns to support Firebird index limitations
59 Person
.connection
.add_column
"people", "last_name", :string, :limit => 100
60 Person
.connection
.add_column
"people", "key", :string, :limit => 100
61 Person
.connection
.add_column
"people", "administrator", :boolean
63 assert_nothing_raised
{ Person
.connection
.add_index("people", "last_name") }
64 assert_nothing_raised
{ Person
.connection
.remove_index("people", "last_name") }
66 # Orcl nds shrt indx nms. Sybs 2.
67 # OpenBase does not have named indexes. You must specify a single column name
68 unless current_adapter
?(:OracleAdapter, :SybaseAdapter, :OpenBaseAdapter)
69 assert_nothing_raised
{ Person
.connection
.add_index("people", ["last_name", "first_name"]) }
70 assert_nothing_raised
{ Person
.connection
.remove_index("people", :column => ["last_name", "first_name"]) }
71 assert_nothing_raised
{ Person
.connection
.add_index("people", ["last_name", "first_name"]) }
72 assert_nothing_raised
{ Person
.connection
.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
73 assert_nothing_raised
{ Person
.connection
.add_index("people", ["last_name", "first_name"]) }
74 assert_nothing_raised
{ Person
.connection
.remove_index("people", "last_name_and_first_name") }
75 assert_nothing_raised
{ Person
.connection
.add_index("people", ["last_name", "first_name"]) }
76 assert_nothing_raised
{ Person
.connection
.remove_index("people", ["last_name", "first_name"]) }
80 # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
81 # OpenBase does not have named indexes. You must specify a single column name
82 unless current_adapter
?(:OpenBaseAdapter)
83 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)
84 assert_nothing_raised
{ Person
.connection
.add_index("people", ["key"], :name => "key_idx", :unique => true) }
85 assert_nothing_raised
{ Person
.connection
.remove_index("people", :name => "key_idx", :unique => true) }
88 # Sybase adapter does not support indexes on :boolean columns
89 # OpenBase does not have named indexes. You must specify a single column
90 unless current_adapter
?(:SybaseAdapter, :OpenBaseAdapter)
91 assert_nothing_raised
{ Person
.connection
.add_index("people", %w(last_name first_name administrator
), :name => "named_admin") }
92 assert_nothing_raised
{ Person
.connection
.remove_index("people", :name => "named_admin") }
96 def testing_table_with_only_foo_attribute
97 Person
.connection
.create_table
:testings, :id => false do |t
|
98 t
.column
:foo, :string
101 yield Person
.connection
103 Person
.connection
.drop_table
:testings rescue nil
105 protected
:testing_table_with_only_foo_attribute
107 def test_create_table_without_id
108 testing_table_with_only_foo_attribute
do |connection
|
109 assert_equal connection
.columns(:testings).size
, 1
113 def test_add_column_with_primary_key_attribute
114 testing_table_with_only_foo_attribute
do |connection
|
115 assert_nothing_raised
{ connection
.add_column
:testings, :id, :primary_key }
116 assert_equal connection
.columns(:testings).size
, 2
120 def test_create_table_adds_id
121 Person
.connection
.create_table
:testings do |t
|
122 t
.column
:foo, :string
125 assert_equal
%w(foo id
),
126 Person
.connection
.columns(:testings).map
{ |c
| c
.name
}.sort
128 Person
.connection
.drop_table
:testings rescue nil
131 def test_create_table_with_not_null_column
132 assert_nothing_raised
do
133 Person
.connection
.create_table
:testings do |t
|
134 t
.column
:foo, :string, :null => false
138 assert_raise(ActiveRecord
::StatementInvalid) do
139 Person
.connection
.execute
"insert into testings (foo) values (NULL)"
142 Person
.connection
.drop_table
:testings rescue nil
145 def test_create_table_with_defaults
146 # MySQL doesn't allow defaults on TEXT or BLOB columns.
147 mysql
= current_adapter
?(:MysqlAdapter)
149 Person
.connection
.create_table
:testings do |t
|
150 t
.column
:one, :string, :default => "hello"
151 t
.column
:two, :boolean, :default => true
152 t
.column
:three, :boolean, :default => false
153 t
.column
:four, :integer, :default => 1
154 t
.column
:five, :text, :default => "hello" unless mysql
157 columns
= Person
.connection
.columns(:testings)
158 one
= columns
.detect
{ |c
| c
.name
== "one" }
159 two
= columns
.detect
{ |c
| c
.name
== "two" }
160 three
= columns
.detect
{ |c
| c
.name
== "three" }
161 four
= columns
.detect
{ |c
| c
.name
== "four" }
162 five
= columns
.detect
{ |c
| c
.name
== "five" } unless mysql
164 assert_equal
"hello", one
.default
165 assert_equal
true, two
.default
166 assert_equal
false, three
.default
167 assert_equal
1, four
.default
168 assert_equal
"hello", five
.default
unless mysql
171 Person
.connection
.drop_table
:testings rescue nil
174 def test_create_table_with_limits
175 assert_nothing_raised
do
176 Person
.connection
.create_table
:testings do |t
|
177 t
.column
:foo, :string, :limit => 255
179 t
.column
:default_int, :integer
181 t
.column
:one_int, :integer, :limit => 1
182 t
.column
:four_int, :integer, :limit => 4
183 t
.column
:eight_int, :integer, :limit => 8
184 t
.column
:eleven_int, :integer, :limit => 11
188 columns
= Person
.connection
.columns(:testings)
189 foo
= columns
.detect
{ |c
| c
.name
== "foo" }
190 assert_equal
255, foo
.limit
192 default
= columns
.detect
{ |c
| c
.name
== "default_int" }
193 one
= columns
.detect
{ |c
| c
.name
== "one_int" }
194 four
= columns
.detect
{ |c
| c
.name
== "four_int" }
195 eight
= columns
.detect
{ |c
| c
.name
== "eight_int" }
196 eleven
= columns
.detect
{ |c
| c
.name
== "eleven_int" }
198 if current_adapter
?(:PostgreSQLAdapter)
199 assert_equal
'integer', default
.sql_type
200 assert_equal
'smallint', one
.sql_type
201 assert_equal
'integer', four
.sql_type
202 assert_equal
'bigint', eight
.sql_type
203 assert_equal
'integer', eleven
.sql_type
204 elsif current_adapter
?(:MysqlAdapter)
205 assert_match
'int(11)', default
.sql_type
206 assert_match
'tinyint', one
.sql_type
207 assert_match
'int', four
.sql_type
208 assert_match
'bigint', eight
.sql_type
209 assert_match
'int(11)', eleven
.sql_type
210 elsif current_adapter
?(:OracleAdapter)
211 assert_equal
'NUMBER(38)', default
.sql_type
212 assert_equal
'NUMBER(1)', one
.sql_type
213 assert_equal
'NUMBER(4)', four
.sql_type
214 assert_equal
'NUMBER(8)', eight
.sql_type
217 Person
.connection
.drop_table
:testings rescue nil
220 def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
221 ActiveRecord
::Base.primary_key_prefix_type
= :table_name_with_underscore
223 Person
.connection
.create_table
:testings do |t
|
224 t
.column
:foo, :string
227 assert_equal
%w(foo testings_id
), Person
.connection
.columns(:testings).map
{ |c
| c
.name
}.sort
229 Person
.connection
.drop_table
:testings rescue nil
230 ActiveRecord
::Base.primary_key_prefix_type
= nil
233 def test_create_table_with_primary_key_prefix_as_table_name
234 ActiveRecord
::Base.primary_key_prefix_type
= :table_name
236 Person
.connection
.create_table
:testings do |t
|
237 t
.column
:foo, :string
240 assert_equal
%w(foo testingsid
), Person
.connection
.columns(:testings).map
{ |c
| c
.name
}.sort
242 Person
.connection
.drop_table
:testings rescue nil
243 ActiveRecord
::Base.primary_key_prefix_type
= nil
246 def test_create_table_with_force_true_does_not_drop_nonexisting_table
247 if Person
.connection
.table_exists
?(:testings2)
248 Person
.connection
.drop_table
:testings2
251 # using a copy as we need the drop_table method to
252 # continue to work for the ensure block of the test
253 temp_conn
= Person
.connection
.dup
254 temp_conn
.expects(:drop_table).never
255 temp_conn
.create_table
:testings2, :force => true do |t
|
256 t
.column
:foo, :string
259 Person
.connection
.drop_table
:testings2 rescue nil
262 def test_create_table_with_timestamps_should_create_datetime_columns
263 table_name
= :testings
265 Person
.connection
.create_table table_name
do |t
|
268 created_columns
= Person
.connection
.columns(table_name
)
270 created_at_column
= created_columns
.detect
{|c
| c
.name
== 'created_at' }
271 updated_at_column
= created_columns
.detect
{|c
| c
.name
== 'updated_at' }
273 assert created_at_column
.null
274 assert updated_at_column
.null
276 Person
.connection
.drop_table table_name
rescue nil
279 def test_create_table_with_timestamps_should_create_datetime_columns_with_options
280 table_name
= :testings
282 Person
.connection
.create_table table_name
do |t
|
283 t
.timestamps
:null => false
285 created_columns
= Person
.connection
.columns(table_name
)
287 created_at_column
= created_columns
.detect
{|c
| c
.name
== 'created_at' }
288 updated_at_column
= created_columns
.detect
{|c
| c
.name
== 'updated_at' }
290 assert
!created_at_column
.null
291 assert
!updated_at_column
.null
293 Person
.connection
.drop_table table_name
rescue nil
296 # Sybase, and SQLite3 will not allow you to add a NOT NULL
297 # column to a table without a default value.
298 unless current_adapter
?(:SybaseAdapter, :SQLiteAdapter)
299 def test_add_column_not_null_without_default
300 Person
.connection
.create_table
:testings do |t
|
301 t
.column
:foo, :string
303 Person
.connection
.add_column
:testings, :bar, :string, :null => false
305 assert_raise(ActiveRecord
::StatementInvalid) do
306 Person
.connection
.execute
"insert into testings (foo, bar) values ('hello', NULL)"
309 Person
.connection
.drop_table
:testings rescue nil
313 def test_add_column_not_null_with_default
314 Person
.connection
.create_table
:testings do |t
|
315 t
.column
:foo, :string
318 con
= Person
.connection
319 Person
.connection
.enable_identity_insert("testings", true) if current_adapter
?(:SybaseAdapter)
320 Person
.connection
.execute
"insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
321 Person
.connection
.enable_identity_insert("testings", false) if current_adapter
?(:SybaseAdapter)
322 assert_nothing_raised
{Person
.connection
.add_column
:testings, :bar, :string, :null => false, :default => "default" }
324 assert_raise(ActiveRecord
::StatementInvalid) do
325 unless current_adapter
?(:OpenBaseAdapter)
326 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)"
328 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)",
329 "Testing Insert","id",2)
333 Person
.connection
.drop_table
:testings rescue nil
336 # We specifically do a manual INSERT here, and then test only the SELECT
337 # functionality. This allows us to more easily catch INSERT being broken,
338 # but SELECT actually working fine.
339 def test_native_decimal_insert_manual_vs_automatic
340 correct_value
= '0012345678901234567890.0123456789'.to_d
343 Person
.connection
.add_column
"people", "wealth", :decimal, :precision => '30', :scale => '10'
344 Person
.reset_column_information
346 # Do a manual insertion
347 if current_adapter
?(:OracleAdapter)
348 Person
.connection
.execute
"insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
349 elsif current_adapter
?(:OpenBaseAdapter) || (current_adapter
?(:MysqlAdapter) && Mysql
.client_version
< 50003) #before mysql 5.0.3 decimals stored as strings
350 Person
.connection
.execute
"insert into people (wealth) values ('12345678901234567890.0123456789')"
352 Person
.connection
.execute
"insert into people (wealth) values (12345678901234567890.0123456789)"
356 row
= Person
.find(:first)
357 assert_kind_of BigDecimal
, row
.wealth
359 # If this assert fails, that means the SELECT is broken!
360 unless current_adapter
?(:SQLite3Adapter)
361 assert_equal correct_value
, row
.wealth
367 # Now use the Rails insertion
368 assert_nothing_raised
{ Person
.create
:wealth => BigDecimal
.new("12345678901234567890.0123456789") }
371 row
= Person
.find(:first)
372 assert_kind_of BigDecimal
, row
.wealth
374 # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
375 unless current_adapter
?(:SQLite3Adapter)
376 assert_equal correct_value
, row
.wealth
380 Person
.connection
.del_column
"people", "wealth" rescue nil
381 Person
.reset_column_information
384 def test_add_column_with_precision_and_scale
385 Person
.connection
.add_column
'people', 'wealth', :decimal, :precision => 9, :scale => 7
386 Person
.reset_column_information
388 wealth_column
= Person
.columns_hash
['wealth']
389 assert_equal
9, wealth_column
.precision
390 assert_equal
7, wealth_column
.scale
393 def test_native_types
395 Person
.connection
.add_column
"people", "last_name", :string
396 Person
.connection
.add_column
"people", "bio", :text
397 Person
.connection
.add_column
"people", "age", :integer
398 Person
.connection
.add_column
"people", "height", :float
399 Person
.connection
.add_column
"people", "wealth", :decimal, :precision => '30', :scale => '10'
400 Person
.connection
.add_column
"people", "birthday", :datetime
401 Person
.connection
.add_column
"people", "favorite_day", :date
402 Person
.connection
.add_column
"people", "moment_of_truth", :datetime
403 Person
.connection
.add_column
"people", "male", :boolean
404 Person
.reset_column_information
406 assert_nothing_raised
do
407 Person
.create
:first_name => 'bob', :last_name => 'bobsen',
408 :bio => "I was born ....", :age => 18, :height => 1.78,
409 :wealth => BigDecimal
.new("12345678901234567890.0123456789"),
410 :birthday => 18.years
.ago
, :favorite_day => 10.days
.ago
,
411 :moment_of_truth => "1782-10-10 21:40:18", :male => true
414 bob
= Person
.find(:first)
415 assert_equal
'bob', bob
.first_name
416 assert_equal
'bobsen', bob
.last_name
417 assert_equal
"I was born ....", bob
.bio
418 assert_equal
18, bob
.age
420 # Test for 30 significent digits (beyond the 16 of float), 10 of them
421 # after the decimal place.
423 unless current_adapter
?(:SQLite3Adapter)
424 assert_equal BigDecimal
.new("0012345678901234567890.0123456789"), bob
.wealth
427 assert_equal
true, bob
.male
?
429 assert_equal String
, bob
.first_name
.class
430 assert_equal String
, bob
.last_name
.class
431 assert_equal String
, bob
.bio
.class
432 assert_equal Fixnum
, bob
.age
.class
433 assert_equal Time
, bob
.birthday
.class
435 if current_adapter
?(:OracleAdapter, :SybaseAdapter)
436 # Sybase, and Oracle don't differentiate between date/time
437 assert_equal Time
, bob
.favorite_day
.class
439 assert_equal Date
, bob
.favorite_day
.class
442 # Test DateTime column and defaults, including timezone.
443 # FIXME: moment of truth may be Time on 64-bit platforms.
444 if bob
.moment_of_truth
.is_a
?(DateTime
)
446 with_env_tz
'US/Eastern' do
447 assert_equal DateTime
.local_offset
, bob
.moment_of_truth
.offset
448 assert_not_equal
0, bob
.moment_of_truth
.offset
449 assert_not_equal
"Z", bob
.moment_of_truth
.zone
450 # US/Eastern is -5 hours from GMT
451 assert_equal
Rational(-5, 24), bob
.moment_of_truth
.offset
452 assert_match
/\A-05:?00\Z/, bob
.moment_of_truth
.zone
#ruby 1.8.6 uses HH:MM, prior versions use HHMM
453 assert_equal DateTime
::ITALY, bob
.moment_of_truth
.start
457 assert_equal TrueClass
, bob
.male
?.class
458 assert_kind_of BigDecimal
, bob
.wealth
461 if current_adapter
?(:MysqlAdapter)
462 def test_unabstracted_database_dependent_types
465 ActiveRecord
::Migration.add_column
:people, :intelligence_quotient, :tinyint
466 Person
.reset_column_information
467 assert_match
/tinyint/, Person
.columns_hash
['intelligence_quotient'].sql_type
469 ActiveRecord
::Migration.remove_column
:people, :intelligence_quotient rescue nil
473 def test_add_remove_single_field_using_string_arguments
474 assert
!Person
.column_methods_hash
.include?(:last_name)
476 ActiveRecord
::Migration.add_column
'people', 'last_name', :string
478 Person
.reset_column_information
479 assert Person
.column_methods_hash
.include?(:last_name)
481 ActiveRecord
::Migration.remove_column
'people', 'last_name'
483 Person
.reset_column_information
484 assert
!Person
.column_methods_hash
.include?(:last_name)
487 def test_add_remove_single_field_using_symbol_arguments
488 assert
!Person
.column_methods_hash
.include?(:last_name)
490 ActiveRecord
::Migration.add_column
:people, :last_name, :string
492 Person
.reset_column_information
493 assert Person
.column_methods_hash
.include?(:last_name)
495 ActiveRecord
::Migration.remove_column
:people, :last_name
497 Person
.reset_column_information
498 assert
!Person
.column_methods_hash
.include?(:last_name)
505 Person
.connection
.add_column
"people", "girlfriend", :string
506 Person
.reset_column_information
507 Person
.create
:girlfriend => 'bobette'
509 Person
.connection
.rename_column
"people", "girlfriend", "exgirlfriend"
511 Person
.reset_column_information
512 bob
= Person
.find(:first)
514 assert_equal
"bobette", bob
.exgirlfriend
516 Person
.connection
.remove_column("people", "girlfriend") rescue nil
517 Person
.connection
.remove_column("people", "exgirlfriend") rescue nil
522 def test_rename_column_using_symbol_arguments
524 names_before
= Person
.find(:all).map(&:first_name)
525 Person
.connection
.rename_column
:people, :first_name, :nick_name
526 Person
.reset_column_information
527 assert Person
.column_names
.include?("nick_name")
528 assert_equal names_before
, Person
.find(:all).map(&:nick_name)
530 Person
.connection
.remove_column("people","nick_name")
531 Person
.connection
.add_column("people","first_name", :string)
535 def test_rename_column
537 names_before
= Person
.find(:all).map(&:first_name)
538 Person
.connection
.rename_column
"people", "first_name", "nick_name"
539 Person
.reset_column_information
540 assert Person
.column_names
.include?("nick_name")
541 assert_equal names_before
, Person
.find(:all).map(&:nick_name)
543 Person
.connection
.remove_column("people","nick_name")
544 Person
.connection
.add_column("people","first_name", :string)
548 def test_rename_column_preserves_default_value_not_null
550 default_before
= Developer
.connection
.columns("developers").find
{ |c
| c
.name
== "salary" }.default
551 assert_equal
70000, default_before
552 Developer
.connection
.rename_column
"developers", "salary", "anual_salary"
553 Developer
.reset_column_information
554 assert Developer
.column_names
.include?("anual_salary")
555 default_after
= Developer
.connection
.columns("developers").find
{ |c
| c
.name
== "anual_salary" }.default
556 assert_equal
70000, default_after
558 Developer
.connection
.rename_column
"developers", "anual_salary", "salary"
559 Developer
.reset_column_information
563 def test_rename_nonexistent_column
564 ActiveRecord
::Base.connection
.create_table(:hats) do |table
|
565 table
.column
:hat_name, :string, :default => nil
567 exception
= if current_adapter
?(:PostgreSQLAdapter)
568 ActiveRecord
::StatementInvalid
570 ActiveRecord
::ActiveRecordError
572 assert_raise(exception
) do
573 Person
.connection
.rename_column
"hats", "nonexistent", "should_fail"
576 ActiveRecord
::Base.connection
.drop_table(:hats)
579 def test_rename_column_with_sql_reserved_word
581 assert_nothing_raised
{ Person
.connection
.rename_column
"people", "first_name", "group" }
582 Person
.reset_column_information
583 assert Person
.column_names
.include?("group")
585 Person
.connection
.remove_column("people", "group") rescue nil
586 Person
.connection
.add_column("people", "first_name", :string) rescue nil
590 def test_rename_column_with_an_index
591 ActiveRecord
::Base.connection
.create_table(:hats) do |table
|
592 table
.column
:hat_name, :string, :limit => 100
593 table
.column
:hat_size, :integer
595 Person
.connection
.add_index
:hats, :hat_name
596 assert_nothing_raised
do
597 Person
.connection
.rename_column
"hats", "hat_name", "name"
600 ActiveRecord
::Base.connection
.drop_table(:hats)
603 def test_remove_column_with_index
604 ActiveRecord
::Base.connection
.create_table(:hats) do |table
|
605 table
.column
:hat_name, :string, :limit => 100
606 table
.column
:hat_size, :integer
608 ActiveRecord
::Base.connection
.add_index
"hats", "hat_size"
610 assert_nothing_raised
{ Person
.connection
.remove_column("hats", "hat_size") }
612 ActiveRecord
::Base.connection
.drop_table(:hats)
615 def test_remove_column_with_multi_column_index
616 ActiveRecord
::Base.connection
.create_table(:hats) do |table
|
617 table
.column
:hat_name, :string, :limit => 100
618 table
.column
:hat_size, :integer
619 table
.column
:hat_style, :string, :limit => 100
621 ActiveRecord
::Base.connection
.add_index
"hats", ["hat_style", "hat_size"], :unique => true
623 assert_nothing_raised
{ Person
.connection
.remove_column("hats", "hat_size") }
625 ActiveRecord
::Base.connection
.drop_table(:hats)
628 def test_change_type_of_not_null_column
629 assert_nothing_raised
do
630 Topic
.connection
.change_column
"topics", "written_on", :datetime, :null => false
631 Topic
.reset_column_information
633 Topic
.connection
.change_column
"topics", "written_on", :datetime, :null => false
634 Topic
.reset_column_information
638 def test_rename_table
640 ActiveRecord
::Base.connection
.create_table
:octopuses do |t
|
641 t
.column
:url, :string
643 ActiveRecord
::Base.connection
.rename_table
:octopuses, :octopi
645 # Using explicit id in insert for compatibility across all databases
646 con
= ActiveRecord
::Base.connection
647 con
.enable_identity_insert("octopi", true) if current_adapter
?(:SybaseAdapter)
648 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')" }
649 con
.enable_identity_insert("octopi", false) if current_adapter
?(:SybaseAdapter)
651 assert_equal
'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord
::Base.connection
.select_value("SELECT url FROM octopi WHERE id=1")
654 ActiveRecord
::Base.connection
.drop_table
:octopuses rescue nil
655 ActiveRecord
::Base.connection
.drop_table
:octopi rescue nil
659 def test_change_column_nullability
661 Person
.connection
.add_column
"people", "funny", :boolean
662 Person
.reset_column_information
663 assert Person
.columns_hash
["funny"].null
, "Column 'funny' must initially allow nulls"
664 Person
.connection
.change_column
"people", "funny", :boolean, :null => false, :default => true
665 Person
.reset_column_information
666 assert
!Person
.columns_hash
["funny"].null
, "Column 'funny' must *not* allow nulls at this point"
667 Person
.connection
.change_column
"people", "funny", :boolean, :null => true
668 Person
.reset_column_information
669 assert Person
.columns_hash
["funny"].null
, "Column 'funny' must allow nulls again at this point"
672 def test_rename_table_with_an_index
674 ActiveRecord
::Base.connection
.create_table
:octopuses do |t
|
675 t
.column
:url, :string
677 ActiveRecord
::Base.connection
.add_index
:octopuses, :url
679 ActiveRecord
::Base.connection
.rename_table
:octopuses, :octopi
681 # Using explicit id in insert for compatibility across all databases
682 con
= ActiveRecord
::Base.connection
683 con
.enable_identity_insert("octopi", true) if current_adapter
?(:SybaseAdapter)
684 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')" }
685 con
.enable_identity_insert("octopi", false) if current_adapter
?(:SybaseAdapter)
687 assert_equal
'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord
::Base.connection
.select_value("SELECT url FROM octopi WHERE id=1")
688 assert ActiveRecord
::Base.connection
.indexes(:octopi).first
.columns
.include?("url")
690 ActiveRecord
::Base.connection
.drop_table
:octopuses rescue nil
691 ActiveRecord
::Base.connection
.drop_table
:octopi rescue nil
695 def test_change_column
696 Person
.connection
.add_column
'people', 'age', :integer
697 old_columns
= Person
.connection
.columns(Person
.table_name
, "#{name} Columns")
698 assert old_columns
.find
{ |c
| c
.name
== 'age' and c
.type
== :integer }
700 assert_nothing_raised
{ Person
.connection
.change_column
"people", "age", :string }
702 new_columns
= Person
.connection
.columns(Person
.table_name
, "#{name} Columns")
703 assert_nil new_columns
.find
{ |c
| c
.name
== 'age' and c
.type
== :integer }
704 assert new_columns
.find
{ |c
| c
.name
== 'age' and c
.type
== :string }
706 old_columns
= Topic
.connection
.columns(Topic
.table_name
, "#{name} Columns")
707 assert old_columns
.find
{ |c
| c
.name
== 'approved' and c
.type
== :boolean and c
.default
== true }
708 assert_nothing_raised
{ Topic
.connection
.change_column
:topics, :approved, :boolean, :default => false }
709 new_columns
= Topic
.connection
.columns(Topic
.table_name
, "#{name} Columns")
710 assert_nil new_columns
.find
{ |c
| c
.name
== 'approved' and c
.type
== :boolean and c
.default
== true }
711 assert new_columns
.find
{ |c
| c
.name
== 'approved' and c
.type
== :boolean and c
.default
== false }
712 assert_nothing_raised
{ Topic
.connection
.change_column
:topics, :approved, :boolean, :default => true }
715 def test_change_column_with_nil_default
716 Person
.connection
.add_column
"people", "contributor", :boolean, :default => true
717 Person
.reset_column_information
718 assert Person
.new
.contributor
?
720 assert_nothing_raised
{ Person
.connection
.change_column
"people", "contributor", :boolean, :default => nil }
721 Person
.reset_column_information
722 assert
!Person
.new
.contributor
?
723 assert_nil Person
.new
.contributor
725 Person
.connection
.remove_column("people", "contributor") rescue nil
728 def test_change_column_with_new_default
729 Person
.connection
.add_column
"people", "administrator", :boolean, :default => true
730 Person
.reset_column_information
731 assert Person
.new
.administrator
?
733 assert_nothing_raised
{ Person
.connection
.change_column
"people", "administrator", :boolean, :default => false }
734 Person
.reset_column_information
735 assert
!Person
.new
.administrator
?
737 Person
.connection
.remove_column("people", "administrator") rescue nil
740 def test_change_column_default
741 Person
.connection
.change_column_default
"people", "first_name", "Tester"
742 Person
.reset_column_information
743 assert_equal
"Tester", Person
.new
.first_name
746 def test_change_column_quotes_column_names
747 Person
.connection
.create_table
:testings do |t
|
748 t
.column
:select, :string
751 assert_nothing_raised
{ Person
.connection
.change_column
:testings, :select, :string, :limit => 10 }
753 assert_nothing_raised
{ Person
.connection
.execute
"insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" }
755 Person
.connection
.drop_table
:testings rescue nil
758 def test_keeping_default_and_notnull_constaint_on_change
759 Person
.connection
.create_table
:testings do |t
|
760 t
.column
:title, :string
762 person_klass
= Class
.new(Person
)
763 person_klass
.set_table_name
'testings'
765 person_klass
.connection
.add_column
"testings", "wealth", :integer, :null => false, :default => 99
766 person_klass
.reset_column_information
767 assert_equal
99, person_klass
.columns_hash
["wealth"].default
768 assert_equal
false, person_klass
.columns_hash
["wealth"].null
769 assert_nothing_raised
{person_klass
.connection
.execute("insert into testings (title) values ('tester')")}
771 # change column default to see that column doesn't lose its not null definition
772 person_klass
.connection
.change_column_default
"testings", "wealth", 100
773 person_klass
.reset_column_information
774 assert_equal
100, person_klass
.columns_hash
["wealth"].default
775 assert_equal
false, person_klass
.columns_hash
["wealth"].null
777 # rename column to see that column doesn't lose its not null and/or default definition
778 person_klass
.connection
.rename_column
"testings", "wealth", "money"
779 person_klass
.reset_column_information
780 assert_nil person_klass
.columns_hash
["wealth"]
781 assert_equal
100, person_klass
.columns_hash
["money"].default
782 assert_equal
false, person_klass
.columns_hash
["money"].null
785 person_klass
.connection
.change_column
"testings", "money", :integer, :null => false, :default => 1000
786 person_klass
.reset_column_information
787 assert_equal
1000, person_klass
.columns_hash
["money"].default
788 assert_equal
false, person_klass
.columns_hash
["money"].null
790 # change column, make it nullable and clear default
791 person_klass
.connection
.change_column
"testings", "money", :integer, :null => true, :default => nil
792 person_klass
.reset_column_information
793 assert_nil person_klass
.columns_hash
["money"].default
794 assert_equal
true, person_klass
.columns_hash
["money"].null
796 # change_column_null, make it not nullable and set null values to a default value
797 person_klass
.connection
.execute('UPDATE testings SET money = NULL')
798 person_klass
.connection
.change_column_null
"testings", "money", false, 2000
799 person_klass
.reset_column_information
800 assert_nil person_klass
.columns_hash
["money"].default
801 assert_equal
false, person_klass
.columns_hash
["money"].null
802 assert_equal
[2000], Person
.connection
.select_values("SELECT money FROM testings").map
{ |s
| s
.to_i
}.sort
804 Person
.connection
.drop_table
:testings rescue nil
807 def test_change_column_default_to_null
808 Person
.connection
.change_column_default
"people", "first_name", nil
809 Person
.reset_column_information
810 assert_nil Person
.new
.first_name
814 assert
!Reminder
.table_exists
?
818 assert Reminder
.create("content" => "hello world", "remind_at" => Time
.now
)
819 assert_equal
"hello world", Reminder
.find(:first).content
822 assert_raise(ActiveRecord
::StatementInvalid) { Reminder
.find(:first) }
825 def test_add_table_with_decimals
826 Person
.connection
.drop_table
:big_numbers rescue nil
828 assert
!BigNumber
.table_exists
?
831 assert BigNumber
.create(
832 :bank_balance => 1586.43,
833 :big_bank_balance => BigDecimal("1000234000567.95"),
834 :world_population => 6000000000,
835 :my_house_population => 3,
836 :value_of_e => BigDecimal("2.7182818284590452353602875")
839 b
= BigNumber
.find(:first)
842 assert_not_nil b
.bank_balance
843 assert_not_nil b
.big_bank_balance
844 assert_not_nil b
.world_population
845 assert_not_nil b
.my_house_population
846 assert_not_nil b
.value_of_e
848 # TODO: set world_population >= 2**62 to cover 64-bit platforms and test
850 assert_kind_of Integer
, b
.world_population
851 assert_equal
6000000000, b
.world_population
852 assert_kind_of Fixnum
, b
.my_house_population
853 assert_equal
3, b
.my_house_population
854 assert_kind_of BigDecimal
, b
.bank_balance
855 assert_equal
BigDecimal("1586.43"), b
.bank_balance
856 assert_kind_of BigDecimal
, b
.big_bank_balance
857 assert_equal
BigDecimal("1000234000567.95"), b
.big_bank_balance
859 # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
860 # precision/scale explicitly left out. By the SQL standard, numbers
861 # assigned to this field should be truncated but that's seldom respected.
862 if current_adapter
?(:PostgreSQLAdapter, :SQLite2Adapter)
863 # - PostgreSQL changes the SQL spec on columns declared simply as
864 # "decimal" to something more useful: instead of being given a scale
865 # of 0, they take on the compile-time limit for precision and scale,
866 # so the following should succeed unless you have used really wacky
867 # compilation options
868 # - SQLite2 has the default behavior of preserving all data sent in,
869 # so this happens there too
870 assert_kind_of BigDecimal
, b
.value_of_e
871 assert_equal
BigDecimal("2.7182818284590452353602875"), b
.value_of_e
872 elsif current_adapter
?(:SQLiteAdapter)
873 # - SQLite3 stores a float, in violation of SQL
874 assert_kind_of BigDecimal
, b
.value_of_e
875 assert_equal
BigDecimal("2.71828182845905"), b
.value_of_e
877 # - SQL standard is an integer
878 assert_kind_of Fixnum
, b
.value_of_e
879 assert_equal
2, b
.value_of_e
882 GiveMeBigNumbers
.down
883 assert_raise(ActiveRecord
::StatementInvalid) { BigNumber
.find(:first) }
887 assert
!Person
.column_methods_hash
.include?(:last_name)
888 assert
!Reminder
.table_exists
?
890 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid")
892 assert_equal
3, ActiveRecord
::Migrator.current_version
893 Person
.reset_column_information
894 assert Person
.column_methods_hash
.include?(:last_name)
895 assert Reminder
.create("content" => "hello world", "remind_at" => Time
.now
)
896 assert_equal
"hello world", Reminder
.find(:first).content
898 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/valid")
900 assert_equal
0, ActiveRecord
::Migrator.current_version
901 Person
.reset_column_information
902 assert
!Person
.column_methods_hash
.include?(:last_name)
903 assert_raise(ActiveRecord
::StatementInvalid) { Reminder
.find(:first) }
906 def test_migrator_one_up
907 assert
!Person
.column_methods_hash
.include?(:last_name)
908 assert
!Reminder
.table_exists
?
910 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
912 Person
.reset_column_information
913 assert Person
.column_methods_hash
.include?(:last_name)
914 assert
!Reminder
.table_exists
?
916 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 2)
918 assert Reminder
.create("content" => "hello world", "remind_at" => Time
.now
)
919 assert_equal
"hello world", Reminder
.find(:first).content
922 def test_migrator_one_down
923 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid")
925 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/valid", 1)
927 Person
.reset_column_information
928 assert Person
.column_methods_hash
.include?(:last_name)
929 assert
!Reminder
.table_exists
?
932 def test_migrator_one_up_one_down
933 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
934 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/valid", 0)
936 assert
!Person
.column_methods_hash
.include?(:last_name)
937 assert
!Reminder
.table_exists
?
940 def test_migrator_double_up
941 assert_equal(0, ActiveRecord
::Migrator.current_version
)
942 ActiveRecord
::Migrator.run(:up, MIGRATIONS_ROOT
+ "/valid", 1)
943 assert_nothing_raised
{ ActiveRecord
::Migrator.run(:up, MIGRATIONS_ROOT
+ "/valid", 1) }
944 assert_equal(1, ActiveRecord
::Migrator.current_version
)
947 def test_migrator_double_down
948 assert_equal(0, ActiveRecord
::Migrator.current_version
)
949 ActiveRecord
::Migrator.run(:up, MIGRATIONS_ROOT
+ "/valid", 1)
950 ActiveRecord
::Migrator.run(:down, MIGRATIONS_ROOT
+ "/valid", 1)
951 assert_nothing_raised
{ ActiveRecord
::Migrator.run(:down, MIGRATIONS_ROOT
+ "/valid", 1) }
952 assert_equal(0, ActiveRecord
::Migrator.current_version
)
955 if ActiveRecord
::Base.connection
.supports_ddl_transactions
?
956 def test_migrator_one_up_with_exception_and_rollback
957 assert
!Person
.column_methods_hash
.include?(:last_name)
959 e
= assert_raise(StandardError
) do
960 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/broken", 100)
963 assert_equal
"An error has occurred, this and all later migrations canceled:\n\nSomething broke", e
.message
965 Person
.reset_column_information
966 assert
!Person
.column_methods_hash
.include?(:last_name)
970 def test_finds_migrations
971 migrations
= ActiveRecord
::Migrator.new(:up, MIGRATIONS_ROOT
+ "/valid").migrations
973 [[1, 'PeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index
do |pair
, i
|
974 assert_equal migrations
[i
].version, pair
.first
975 assert_equal migrations
[i
].name
, pair
.last
979 def test_finds_pending_migrations
980 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/interleaved/pass_2", 1)
981 migrations
= ActiveRecord
::Migrator.new(:up, MIGRATIONS_ROOT
+ "/interleaved/pass_2").pending_migrations
983 assert_equal
1, migrations
.size
984 assert_equal migrations
[0].version, 3
985 assert_equal migrations
[0].name
, 'InnocentJointable'
988 def test_only_loads_pending_migrations
990 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
992 # now unload the migrations that have been defined
993 PeopleHaveLastNames
.unloadable
994 ActiveSupport
::Dependencies.remove_unloadable_constants
!
996 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/valid", nil)
998 assert
!defined? PeopleHaveLastNames
1000 %w(WeNeedReminders
, InnocentJointable
).each
do |migration
|
1001 assert
defined? migration
1005 load(MIGRATIONS_ROOT
+ "/valid/1_people_have_last_names.rb")
1008 def test_migrator_interleaved_migrations
1009 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/interleaved/pass_1")
1011 assert_nothing_raised
do
1012 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/interleaved/pass_2")
1015 Person
.reset_column_information
1016 assert Person
.column_methods_hash
.include?(:last_name)
1018 assert_nothing_raised
do
1019 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/interleaved/pass_3")
1023 def test_migrator_db_has_no_schema_migrations_table
1024 ActiveRecord
::Base.connection
.execute("DROP TABLE schema_migrations;")
1025 assert_nothing_raised
do
1026 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/valid", 1)
1030 def test_migrator_verbosity
1031 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
1032 assert PeopleHaveLastNames
.message_count
> 0
1033 PeopleHaveLastNames
.message_count
= 0
1035 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/valid", 0)
1036 assert PeopleHaveLastNames
.message_count
> 0
1037 PeopleHaveLastNames
.message_count
= 0
1040 def test_migrator_verbosity_off
1041 PeopleHaveLastNames
.verbose
= false
1042 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
1043 assert PeopleHaveLastNames
.message_count
.zero
?
1044 ActiveRecord
::Migrator.down(MIGRATIONS_ROOT
+ "/valid", 0)
1045 assert PeopleHaveLastNames
.message_count
.zero
?
1048 def test_migrator_going_down_due_to_version_target
1049 ActiveRecord
::Migrator.up(MIGRATIONS_ROOT
+ "/valid", 1)
1050 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/valid", 0)
1052 assert
!Person
.column_methods_hash
.include?(:last_name)
1053 assert
!Reminder
.table_exists
?
1055 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/valid")
1057 Person
.reset_column_information
1058 assert Person
.column_methods_hash
.include?(:last_name)
1059 assert Reminder
.create("content" => "hello world", "remind_at" => Time
.now
)
1060 assert_equal
"hello world", Reminder
.find(:first).content
1063 def test_migrator_rollback
1064 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/valid")
1065 assert_equal(3, ActiveRecord
::Migrator.current_version
)
1067 ActiveRecord
::Migrator.rollback(MIGRATIONS_ROOT
+ "/valid")
1068 assert_equal(2, ActiveRecord
::Migrator.current_version
)
1070 ActiveRecord
::Migrator.rollback(MIGRATIONS_ROOT
+ "/valid")
1071 assert_equal(1, ActiveRecord
::Migrator.current_version
)
1073 ActiveRecord
::Migrator.rollback(MIGRATIONS_ROOT
+ "/valid")
1074 assert_equal(0, ActiveRecord
::Migrator.current_version
)
1076 ActiveRecord
::Migrator.rollback(MIGRATIONS_ROOT
+ "/valid")
1077 assert_equal(0, ActiveRecord
::Migrator.current_version
)
1080 def test_schema_migrations_table_name
1081 ActiveRecord
::Base.table_name_prefix
= "prefix_"
1082 ActiveRecord
::Base.table_name_suffix
= "_suffix"
1083 Reminder
.reset_table_name
1084 assert_equal
"prefix_schema_migrations_suffix", ActiveRecord
::Migrator.schema_migrations_table_name
1085 ActiveRecord
::Base.table_name_prefix
= ""
1086 ActiveRecord
::Base.table_name_suffix
= ""
1087 Reminder
.reset_table_name
1088 assert_equal
"schema_migrations", ActiveRecord
::Migrator.schema_migrations_table_name
1090 ActiveRecord
::Base.table_name_prefix
= ""
1091 ActiveRecord
::Base.table_name_suffix
= ""
1094 def test_proper_table_name
1095 assert_equal
"table", ActiveRecord
::Migrator.proper_table_name('table')
1096 assert_equal
"table", ActiveRecord
::Migrator.proper_table_name(:table)
1097 assert_equal
"reminders", ActiveRecord
::Migrator.proper_table_name(Reminder
)
1098 Reminder
.reset_table_name
1099 assert_equal Reminder
.table_name
, ActiveRecord
::Migrator.proper_table_name(Reminder
)
1101 # Use the model's own prefix/suffix if a model is given
1102 ActiveRecord
::Base.table_name_prefix
= "ARprefix_"
1103 ActiveRecord
::Base.table_name_suffix
= "_ARsuffix"
1104 Reminder
.table_name_prefix
= 'prefix_'
1105 Reminder
.table_name_suffix
= '_suffix'
1106 Reminder
.reset_table_name
1107 assert_equal
"prefix_reminders_suffix", ActiveRecord
::Migrator.proper_table_name(Reminder
)
1108 Reminder
.table_name_prefix
= ''
1109 Reminder
.table_name_suffix
= ''
1110 Reminder
.reset_table_name
1112 # Use AR::Base's prefix/suffix if string or symbol is given
1113 ActiveRecord
::Base.table_name_prefix
= "prefix_"
1114 ActiveRecord
::Base.table_name_suffix
= "_suffix"
1115 Reminder
.reset_table_name
1116 assert_equal
"prefix_table_suffix", ActiveRecord
::Migrator.proper_table_name('table')
1117 assert_equal
"prefix_table_suffix", ActiveRecord
::Migrator.proper_table_name(:table)
1118 ActiveRecord
::Base.table_name_prefix
= ""
1119 ActiveRecord
::Base.table_name_suffix
= ""
1120 Reminder
.reset_table_name
1123 def test_add_drop_table_with_prefix_and_suffix
1124 assert
!Reminder
.table_exists
?
1125 ActiveRecord
::Base.table_name_prefix
= 'prefix_'
1126 ActiveRecord
::Base.table_name_suffix
= '_suffix'
1127 Reminder
.reset_table_name
1128 Reminder
.reset_sequence_name
1130 assert Reminder
.create("content" => "hello world", "remind_at" => Time
.now
)
1131 assert_equal
"hello world", Reminder
.find(:first).content
1133 WeNeedReminders
.down
1134 assert_raise(ActiveRecord
::StatementInvalid) { Reminder
.find(:first) }
1136 ActiveRecord
::Base.table_name_prefix
= ''
1137 ActiveRecord
::Base.table_name_suffix
= ''
1138 Reminder
.reset_table_name
1139 Reminder
.reset_sequence_name
1142 def test_create_table_with_binary_column
1143 Person
.connection
.drop_table
:binary_testings rescue nil
1145 assert_nothing_raised
{
1146 Person
.connection
.create_table
:binary_testings do |t
|
1147 t
.column
"data", :binary, :null => false
1151 columns
= Person
.connection
.columns(:binary_testings)
1152 data_column
= columns
.detect
{ |c
| c
.name
== "data" }
1154 if current_adapter
?(:MysqlAdapter)
1155 assert_equal
'', data_column
.default
1157 assert_nil data_column
.default
1160 Person
.connection
.drop_table
:binary_testings rescue nil
1163 def test_migrator_with_duplicates
1164 assert_raise(ActiveRecord
::DuplicateMigrationVersionError) do
1165 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/duplicate", nil)
1169 def test_migrator_with_duplicate_names
1170 assert_raise(ActiveRecord
::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do
1171 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/duplicate_names", nil)
1175 def test_migrator_with_missing_version_numbers
1176 assert_raise(ActiveRecord
::UnknownMigrationVersionError) do
1177 ActiveRecord
::Migrator.migrate(MIGRATIONS_ROOT
+ "/missing", 500)
1181 def test_create_table_with_custom_sequence_name
1182 return unless current_adapter
? :OracleAdapter
1184 # table name is 29 chars, the standard sequence name will
1185 # be 33 chars and fail
1186 assert_raise(ActiveRecord
::StatementInvalid) do
1188 Person
.connection
.create_table
:table_with_name_thats_just_ok do |t
|
1189 t
.column
:foo, :string, :null => false
1192 Person
.connection
.drop_table
:table_with_name_thats_just_ok rescue nil
1196 # should be all good w/ a custom sequence name
1197 assert_nothing_raised
do
1199 Person
.connection
.create_table
:table_with_name_thats_just_ok,
1200 :sequence_name => 'suitably_short_seq' do |t
|
1201 t
.column
:foo, :string, :null => false
1204 Person
.connection
.execute("select suitably_short_seq.nextval from dual")
1207 Person
.connection
.drop_table
:table_with_name_thats_just_ok,
1208 :sequence_name => 'suitably_short_seq' rescue nil
1212 # confirm the custom sequence got dropped
1213 assert_raise(ActiveRecord
::StatementInvalid) do
1214 Person
.connection
.execute("select suitably_short_seq.nextval from dual")
1219 def with_env_tz(new_tz
= 'US/Eastern')
1220 old_tz
, ENV['TZ'] = ENV['TZ'], new_tz
1223 old_tz
? ENV['TZ'] = old_tz
: ENV.delete('TZ')
1228 class SexyMigrationsTest
< ActiveRecord
::TestCase
1229 def test_references_column_type_adds_id
1230 with_new_table
do |t
|
1231 t
.expects(:column).with('customer_id', :integer, {})
1232 t
.references
:customer
1236 def test_references_column_type_with_polymorphic_adds_type
1237 with_new_table
do |t
|
1238 t
.expects(:column).with('taggable_type', :string, {})
1239 t
.expects(:column).with('taggable_id', :integer, {})
1240 t
.references
:taggable, :polymorphic => true
1244 def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1245 with_new_table
do |t
|
1246 t
.expects(:column).with('taggable_type', :string, {:null => false})
1247 t
.expects(:column).with('taggable_id', :integer, {:null => false})
1248 t
.references
:taggable, :polymorphic => true, :null => false
1252 def test_belongs_to_works_like_references
1253 with_new_table
do |t
|
1254 t
.expects(:column).with('customer_id', :integer, {})
1255 t
.belongs_to
:customer
1259 def test_timestamps_creates_updated_at_and_created_at
1260 with_new_table
do |t
|
1261 t
.expects(:column).with(:created_at, :datetime, kind_of(Hash
))
1262 t
.expects(:column).with(:updated_at, :datetime, kind_of(Hash
))
1267 def test_integer_creates_integer_column
1268 with_new_table
do |t
|
1269 t
.expects(:column).with(:foo, 'integer', {})
1270 t
.expects(:column).with(:bar, 'integer', {})
1271 t
.integer
:foo, :bar
1275 def test_string_creates_string_column
1276 with_new_table
do |t
|
1277 t
.expects(:column).with(:foo, 'string', {})
1278 t
.expects(:column).with(:bar, 'string', {})
1285 Person
.connection
.create_table
:delete_me, :force => true do |t
|
1289 Person
.connection
.drop_table
:delete_me rescue nil
1292 end # SexyMigrationsTest
1294 class ChangeTableMigrationsTest
< ActiveRecord
::TestCase
1296 @connection = Person
.connection
1297 @connection.create_table
:delete_me, :force => true do |t
|
1302 Person
.connection
.drop_table
:delete_me rescue nil
1305 def test_references_column_type_adds_id
1306 with_change_table
do |t
|
1307 @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1308 t
.references
:customer
1312 def test_remove_references_column_type_removes_id
1313 with_change_table
do |t
|
1314 @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1315 t
.remove_references
:customer
1319 def test_add_belongs_to_works_like_add_references
1320 with_change_table
do |t
|
1321 @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {})
1322 t
.belongs_to
:customer
1326 def test_remove_belongs_to_works_like_remove_references
1327 with_change_table
do |t
|
1328 @connection.expects(:remove_column).with(:delete_me, 'customer_id')
1329 t
.remove_belongs_to
:customer
1333 def test_references_column_type_with_polymorphic_adds_type
1334 with_change_table
do |t
|
1335 @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {})
1336 @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {})
1337 t
.references
:taggable, :polymorphic => true
1341 def test_remove_references_column_type_with_polymorphic_removes_type
1342 with_change_table
do |t
|
1343 @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1344 @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1345 t
.remove_references
:taggable, :polymorphic => true
1349 def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
1350 with_change_table
do |t
|
1351 @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false})
1352 @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false})
1353 t
.references
:taggable, :polymorphic => true, :null => false
1357 def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
1358 with_change_table
do |t
|
1359 @connection.expects(:remove_column).with(:delete_me, 'taggable_type')
1360 @connection.expects(:remove_column).with(:delete_me, 'taggable_id')
1361 t
.remove_references
:taggable, :polymorphic => true, :null => false
1365 def test_timestamps_creates_updated_at_and_created_at
1366 with_change_table
do |t
|
1367 @connection.expects(:add_timestamps).with(:delete_me)
1372 def test_remove_timestamps_creates_updated_at_and_created_at
1373 with_change_table
do |t
|
1374 @connection.expects(:remove_timestamps).with(:delete_me)
1380 if current_adapter
?(:PostgreSQLAdapter)
1381 "character varying(255)"
1388 if current_adapter
?(:MysqlAdapter)
1395 def test_integer_creates_integer_column
1396 with_change_table
do |t
|
1397 @connection.expects(:add_column).with(:delete_me, :foo, integer_column
, {})
1398 @connection.expects(:add_column).with(:delete_me, :bar, integer_column
, {})
1399 t
.integer
:foo, :bar
1403 def test_string_creates_string_column
1404 with_change_table
do |t
|
1405 @connection.expects(:add_column).with(:delete_me, :foo, string_column
, {})
1406 @connection.expects(:add_column).with(:delete_me, :bar, string_column
, {})
1411 def test_column_creates_column
1412 with_change_table
do |t
|
1413 @connection.expects(:add_column).with(:delete_me, :bar, :integer, {})
1414 t
.column
:bar, :integer
1418 def test_column_creates_column_with_options
1419 with_change_table
do |t
|
1420 @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false})
1421 t
.column
:bar, :integer, :null => false
1425 def test_index_creates_index
1426 with_change_table
do |t
|
1427 @connection.expects(:add_index).with(:delete_me, :bar, {})
1432 def test_index_creates_index_with_options
1433 with_change_table
do |t
|
1434 @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true})
1435 t
.index
:bar, :unique => true
1439 def test_change_changes_column
1440 with_change_table
do |t
|
1441 @connection.expects(:change_column).with(:delete_me, :bar, :string, {})
1442 t
.change
:bar, :string
1446 def test_change_changes_column_with_options
1447 with_change_table
do |t
|
1448 @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true})
1449 t
.change
:bar, :string, :null => true
1453 def test_change_default_changes_column
1454 with_change_table
do |t
|
1455 @connection.expects(:change_column_default).with(:delete_me, :bar, :string)
1456 t
.change_default
:bar, :string
1460 def test_remove_drops_single_column
1461 with_change_table
do |t
|
1462 @connection.expects(:remove_column).with(:delete_me, [:bar])
1467 def test_remove_drops_multiple_columns
1468 with_change_table
do |t
|
1469 @connection.expects(:remove_column).with(:delete_me, [:bar, :baz])
1474 def test_remove_index_removes_index_with_options
1475 with_change_table
do |t
|
1476 @connection.expects(:remove_index).with(:delete_me, {:unique => true})
1477 t
.remove_index
:unique => true
1481 def test_rename_renames_column
1482 with_change_table
do |t
|
1483 @connection.expects(:rename_column).with(:delete_me, :bar, :baz)
1489 def with_change_table
1490 Person
.connection
.change_table
:delete_me do |t
|