2008-01-21 17:20:51 +00:00
require " cases/helper "
2006-07-08 20:35:56 +00:00
require 'bigdecimal/util'
2008-01-18 07:31:37 +00:00
require 'models/person'
require 'models/topic'
2008-07-14 06:40:05 +00:00
require 'models/developer'
2008-01-21 17:20:51 +00:00
require MIGRATIONS_ROOT + " /valid/1_people_have_last_names "
require MIGRATIONS_ROOT + " /valid/2_we_need_reminders "
require MIGRATIONS_ROOT + " /decimal/1_give_me_big_numbers "
2008-04-09 16:20:15 +00:00
require MIGRATIONS_ROOT + " /interleaved/pass_3/2_i_raise_on_down "
2005-07-04 18:51:02 +00:00
2006-07-07 10:48:43 +00:00
if ActiveRecord :: Base . connection . supports_migrations?
2006-07-08 20:35:56 +00:00
class BigNumber < ActiveRecord :: Base ; end
2005-07-04 18:51:02 +00:00
class Reminder < ActiveRecord :: Base ; end
2006-03-04 18:46:51 +00:00
class ActiveRecord :: Migration
class << self
attr_accessor :message_count
def puts ( text = " " )
self . message_count || = 0
self . message_count += 1
end
end
end
2008-01-21 17:20:51 +00:00
class MigrationTest < ActiveRecord :: TestCase
2005-09-23 15:00:56 +00:00
self . use_transactional_fixtures = false
2008-01-18 07:30:42 +00:00
2007-09-22 18:23:30 +00:00
fixtures :people
2005-09-23 15:00:56 +00:00
2005-07-04 18:51:02 +00:00
def setup
2006-03-04 18:46:51 +00:00
ActiveRecord :: Migration . verbose = true
PeopleHaveLastNames . message_count = 0
2005-07-04 18:51:02 +00:00
end
def teardown
2008-04-09 16:20:15 +00:00
ActiveRecord :: Base . connection . initialize_schema_migrations_table
ActiveRecord :: Base . connection . execute " DELETE FROM #{ ActiveRecord :: Migrator . schema_migrations_table_name } "
2005-07-04 18:51:02 +00:00
2006-07-08 20:35:56 +00:00
%w( reminders people_reminders prefix_reminders_suffix ) . each do | table |
Reminder . connection . drop_table ( table ) rescue nil
end
2005-07-04 18:51:02 +00:00
Reminder . reset_column_information
2006-07-10 18:24:35 +00:00
%w( last_name key bio age height wealth birthday favorite_day
2007-10-07 04:52:09 +00:00
moment_of_truth male administrator funny ) . each do | column |
2006-07-08 20:35:56 +00:00
Person . connection . remove_column ( 'people' , column ) rescue nil
end
2006-07-08 17:13:21 +00:00
Person . connection . remove_column ( " people " , " first_name " ) rescue nil
2006-08-23 05:49:40 +00:00
Person . connection . remove_column ( " people " , " middle_name " ) rescue nil
2006-07-08 17:13:21 +00:00
Person . connection . add_column ( " people " , " first_name " , :string , :limit = > 40 )
2005-07-04 18:51:02 +00:00
Person . reset_column_information
end
2005-12-20 21:43:47 +00:00
2005-07-05 07:19:20 +00:00
def test_add_index
2006-07-08 17:13:21 +00:00
# Limit size of last_name and key columns to support Firebird index limitations
Person . connection . add_column " people " , " last_name " , :string , :limit = > 100
Person . connection . add_column " people " , " key " , :string , :limit = > 100
2005-09-23 13:29:33 +00:00
Person . connection . add_column " people " , " administrator " , :boolean
2006-07-07 10:48:43 +00:00
2005-07-05 07:19:20 +00:00
assert_nothing_raised { Person . connection . add_index ( " people " , " last_name " ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , " last_name " ) }
2007-01-05 00:12:06 +00:00
# Orcl nds shrt indx nms. Sybs 2.
2007-09-13 23:21:14 +00:00
# OpenBase does not have named indexes. You must specify a single column name
unless current_adapter? ( :OracleAdapter , :SybaseAdapter , :OpenBaseAdapter )
2006-08-15 23:51:27 +00:00
assert_nothing_raised { Person . connection . add_index ( " people " , [ " last_name " , " first_name " ] ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , :column = > [ " last_name " , " first_name " ] ) }
assert_nothing_raised { Person . connection . add_index ( " people " , [ " last_name " , " first_name " ] ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , :name = > " index_people_on_last_name_and_first_name " ) }
assert_nothing_raised { Person . connection . add_index ( " people " , [ " last_name " , " first_name " ] ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , " last_name_and_first_name " ) }
assert_nothing_raised { Person . connection . add_index ( " people " , [ " last_name " , " first_name " ] ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , [ " last_name " , " first_name " ] ) }
end
2006-07-07 10:48:43 +00:00
2006-04-20 02:41:05 +00:00
# quoting
2006-07-08 17:13:21 +00:00
# Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
2007-09-13 23:21:14 +00:00
# OpenBase does not have named indexes. You must specify a single column name
unless current_adapter? ( :OpenBaseAdapter )
2008-04-23 02:23:53 +00:00
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)
2007-09-13 23:21:14 +00:00
assert_nothing_raised { Person . connection . add_index ( " people " , [ " key " ] , :name = > " key_idx " , :unique = > true ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , :name = > " key_idx " , :unique = > true ) }
end
2008-01-18 07:30:42 +00:00
2006-03-18 03:02:32 +00:00
# Sybase adapter does not support indexes on :boolean columns
2007-09-13 23:21:14 +00:00
# OpenBase does not have named indexes. You must specify a single column
unless current_adapter? ( :SybaseAdapter , :OpenBaseAdapter )
2006-03-18 03:02:32 +00:00
assert_nothing_raised { Person . connection . add_index ( " people " , %w( last_name first_name administrator ) , :name = > " named_admin " ) }
assert_nothing_raised { Person . connection . remove_index ( " people " , :name = > " named_admin " ) }
end
2005-07-05 07:19:20 +00:00
end
2005-07-27 17:06:22 +00:00
def test_create_table_adds_id
Person . connection . create_table :testings do | t |
t . column :foo , :string
end
assert_equal %w( foo id ) ,
Person . connection . columns ( :testings ) . map { | c | c . name } . sort
ensure
Person . connection . drop_table :testings rescue nil
end
2005-07-30 10:16:21 +00:00
def test_create_table_with_not_null_column
2007-01-15 02:22:53 +00:00
assert_nothing_raised do
Person . connection . create_table :testings do | t |
t . column :foo , :string , :null = > false
end
2005-07-30 10:16:21 +00:00
end
assert_raises ( ActiveRecord :: StatementInvalid ) do
Person . connection . execute " insert into testings (foo) values (NULL) "
end
ensure
Person . connection . drop_table :testings rescue nil
end
2005-09-25 15:49:35 +00:00
def test_create_table_with_defaults
2007-02-11 09:17:10 +00:00
# MySQL doesn't allow defaults on TEXT or BLOB columns.
mysql = current_adapter? ( :MysqlAdapter )
2005-09-25 15:49:35 +00:00
Person . connection . create_table :testings do | t |
t . column :one , :string , :default = > " hello "
t . column :two , :boolean , :default = > true
t . column :three , :boolean , :default = > false
t . column :four , :integer , :default = > 1
2007-02-11 09:17:10 +00:00
t . column :five , :text , :default = > " hello " unless mysql
2005-09-25 15:49:35 +00:00
end
columns = Person . connection . columns ( :testings )
one = columns . detect { | c | c . name == " one " }
two = columns . detect { | c | c . name == " two " }
three = columns . detect { | c | c . name == " three " }
four = columns . detect { | c | c . name == " four " }
2007-02-11 09:17:10 +00:00
five = columns . detect { | c | c . name == " five " } unless mysql
2005-09-25 15:49:35 +00:00
assert_equal " hello " , one . default
2006-05-21 15:13:28 +00:00
assert_equal true , two . default
assert_equal false , three . default
2005-09-25 15:49:35 +00:00
assert_equal 1 , four . default
2007-02-11 09:17:10 +00:00
assert_equal " hello " , five . default unless mysql
2005-09-25 15:49:35 +00:00
ensure
Person . connection . drop_table :testings rescue nil
end
2006-05-12 03:59:43 +00:00
def test_create_table_with_limits
2006-05-12 05:15:17 +00:00
assert_nothing_raised do
Person . connection . create_table :testings do | t |
t . column :foo , :string , :limit = > 255
2006-05-12 03:59:43 +00:00
2006-05-12 05:15:17 +00:00
t . column :default_int , :integer
2006-05-12 03:59:43 +00:00
2008-06-27 08:06:33 +00:00
t . column :one_int , :integer , :limit = > 1
t . column :four_int , :integer , :limit = > 4
t . column :eight_int , :integer , :limit = > 8
t . column :eleven_int , :integer , :limit = > 11
2006-05-12 05:15:17 +00:00
end
2006-05-12 03:59:43 +00:00
end
columns = Person . connection . columns ( :testings )
foo = columns . detect { | c | c . name == " foo " }
assert_equal 255 , foo . limit
default = columns . detect { | c | c . name == " default_int " }
one = columns . detect { | c | c . name == " one_int " }
four = columns . detect { | c | c . name == " four_int " }
eight = columns . detect { | c | c . name == " eight_int " }
2008-06-27 08:06:33 +00:00
eleven = columns . detect { | c | c . name == " eleven_int " }
2006-05-12 03:59:43 +00:00
if current_adapter? ( :PostgreSQLAdapter )
assert_equal 'integer' , default . sql_type
assert_equal 'smallint' , one . sql_type
assert_equal 'integer' , four . sql_type
assert_equal 'bigint' , eight . sql_type
2008-06-27 08:06:33 +00:00
assert_equal 'integer' , eleven . sql_type
2008-06-15 02:55:56 +00:00
elsif current_adapter? ( :MysqlAdapter )
2008-06-27 08:06:33 +00:00
assert_match 'int(11)' , default . sql_type
assert_match 'tinyint' , one . sql_type
assert_match 'int' , four . sql_type
assert_match 'bigint' , eight . sql_type
assert_match 'int(11)' , eleven . sql_type
2006-05-21 15:13:28 +00:00
elsif current_adapter? ( :OracleAdapter )
assert_equal 'NUMBER(38)' , default . sql_type
assert_equal 'NUMBER(1)' , one . sql_type
assert_equal 'NUMBER(4)' , four . sql_type
assert_equal 'NUMBER(8)' , eight . sql_type
2006-05-12 03:59:43 +00:00
end
ensure
Person . connection . drop_table :testings rescue nil
end
2006-07-07 10:48:43 +00:00
2008-03-18 18:23:14 +00:00
def test_create_table_with_primary_key_prefix_as_table_name_with_underscore
ActiveRecord :: Base . primary_key_prefix_type = :table_name_with_underscore
Person . connection . create_table :testings do | t |
t . column :foo , :string
end
assert_equal %w( foo testings_id ) , Person . connection . columns ( :testings ) . map { | c | c . name } . sort
ensure
Person . connection . drop_table :testings rescue nil
ActiveRecord :: Base . primary_key_prefix_type = nil
end
def test_create_table_with_primary_key_prefix_as_table_name
ActiveRecord :: Base . primary_key_prefix_type = :table_name
Person . connection . create_table :testings do | t |
t . column :foo , :string
end
assert_equal %w( foo testingsid ) , Person . connection . columns ( :testings ) . map { | c | c . name } . sort
ensure
Person . connection . drop_table :testings rescue nil
ActiveRecord :: Base . primary_key_prefix_type = nil
end
2008-05-06 23:08:57 +00:00
uses_mocha ( 'test_create_table_with_force_true_does_not_drop_nonexisting_table' ) do
def test_create_table_with_force_true_does_not_drop_nonexisting_table
if Person . connection . table_exists? ( :testings2 )
Person . connection . drop_table :testings2
end
# using a copy as we need the drop_table method to
# continue to work for the ensure block of the test
temp_conn = Person . connection . dup
temp_conn . expects ( :drop_table ) . never
temp_conn . create_table :testings2 , :force = > true do | t |
t . column :foo , :string
end
ensure
Person . connection . drop_table :testings2 rescue nil
end
end
2008-08-22 11:48:00 +00:00
def test_create_table_with_timestamps_should_create_datetime_columns
table_name = :testings
Person . connection . create_table table_name do | t |
t . timestamps
end
created_columns = Person . connection . columns ( table_name )
created_at_column = created_columns . detect { | c | c . name == 'created_at' }
updated_at_column = created_columns . detect { | c | c . name == 'updated_at' }
assert created_at_column . null
assert updated_at_column . null
ensure
Person . connection . drop_table table_name rescue nil
end
def test_create_table_with_timestamps_should_create_datetime_columns_with_options
table_name = :testings
Person . connection . create_table table_name do | t |
t . timestamps :null = > false
end
created_columns = Person . connection . columns ( table_name )
created_at_column = created_columns . detect { | c | c . name == 'created_at' }
updated_at_column = created_columns . detect { | c | c . name == 'updated_at' }
assert ! created_at_column . null
assert ! updated_at_column . null
ensure
Person . connection . drop_table table_name rescue nil
end
2008-03-18 18:23:14 +00:00
2008-11-19 16:09:44 +00:00
# Sybase, and SQLite3 will not allow you to add a NOT NULL
2006-11-05 02:01:31 +00:00
# column to a table without a default value.
2008-11-19 16:09:44 +00:00
unless current_adapter? ( :SybaseAdapter , :SQLiteAdapter )
2005-10-28 07:40:28 +00:00
def test_add_column_not_null_without_default
Person . connection . create_table :testings do | t |
t . column :foo , :string
end
Person . connection . add_column :testings , :bar , :string , :null = > false
2006-07-07 10:48:43 +00:00
2005-10-28 07:40:28 +00:00
assert_raises ( ActiveRecord :: StatementInvalid ) do
Person . connection . execute " insert into testings (foo, bar) values ('hello', NULL) "
end
ensure
Person . connection . drop_table :testings rescue nil
end
end
2006-07-07 10:48:43 +00:00
2005-10-28 07:40:28 +00:00
def test_add_column_not_null_with_default
2006-07-08 17:13:21 +00:00
Person . connection . create_table :testings do | t |
2005-07-30 10:16:21 +00:00
t . column :foo , :string
end
2008-01-18 07:30:42 +00:00
con = Person . connection
2007-01-05 00:12:06 +00:00
Person . connection . enable_identity_insert ( " testings " , true ) if current_adapter? ( :SybaseAdapter )
2006-07-10 18:24:35 +00:00
Person . connection . execute " insert into testings ( #{ con . quote_column_name ( 'id' ) } , #{ con . quote_column_name ( 'foo' ) } ) values (1, 'hello') "
2007-01-05 00:12:06 +00:00
Person . connection . enable_identity_insert ( " testings " , false ) if current_adapter? ( :SybaseAdapter )
2006-06-03 21:41:40 +00:00
assert_nothing_raised { Person . connection . add_column :testings , :bar , :string , :null = > false , :default = > " default " }
2005-07-30 10:16:21 +00:00
assert_raises ( ActiveRecord :: StatementInvalid ) do
2007-09-13 23:21:14 +00:00
unless current_adapter? ( :OpenBaseAdapter )
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) "
else
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) " ,
" Testing Insert " , " id " , 2 )
end
2005-07-30 10:16:21 +00:00
end
ensure
Person . connection . drop_table :testings rescue nil
end
2006-07-07 10:48:43 +00:00
2006-07-08 20:35:56 +00:00
# We specifically do a manual INSERT here, and then test only the SELECT
# functionality. This allows us to more easily catch INSERT being broken,
# but SELECT actually working fine.
def test_native_decimal_insert_manual_vs_automatic
2007-03-16 21:41:09 +00:00
correct_value = '0012345678901234567890.0123456789' . to_d
2006-07-08 20:35:56 +00:00
Person . delete_all
Person . connection . add_column " people " , " wealth " , :decimal , :precision = > '30' , :scale = > '10'
Person . reset_column_information
# Do a manual insertion
2006-07-10 18:10:50 +00:00
if current_adapter? ( :OracleAdapter )
Person . connection . execute " insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789) "
2008-05-22 10:19:10 +00:00
elsif current_adapter? ( :OpenBaseAdapter ) || ( current_adapter? ( :MysqlAdapter ) && Mysql . client_version < 50003 ) #before mysql 5.0.3 decimals stored as strings
2007-09-13 23:21:14 +00:00
Person . connection . execute " insert into people (wealth) values ('12345678901234567890.0123456789') "
2006-07-10 18:10:50 +00:00
else
Person . connection . execute " insert into people (wealth) values (12345678901234567890.0123456789) "
end
2006-07-08 20:35:56 +00:00
# SELECT
row = Person . find ( :first )
assert_kind_of BigDecimal , row . wealth
# If this assert fails, that means the SELECT is broken!
2007-05-18 01:14:18 +00:00
unless current_adapter? ( :SQLite3Adapter )
assert_equal correct_value , row . wealth
end
2006-07-08 20:35:56 +00:00
# Reset to old state
Person . delete_all
# Now use the Rails insertion
assert_nothing_raised { Person . create :wealth = > BigDecimal . new ( " 12345678901234567890.0123456789 " ) }
# SELECT
row = Person . find ( :first )
assert_kind_of BigDecimal , row . wealth
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
2007-05-18 01:14:18 +00:00
unless current_adapter? ( :SQLite3Adapter )
assert_equal correct_value , row . wealth
end
2006-07-08 20:35:56 +00:00
# Reset to old state
Person . connection . del_column " people " , " wealth " rescue nil
Person . reset_column_information
end
2008-01-16 03:54:15 +00:00
def test_add_column_with_precision_and_scale
Person . connection . add_column 'people' , 'wealth' , :decimal , :precision = > 9 , :scale = > 7
Person . reset_column_information
wealth_column = Person . columns_hash [ 'wealth' ]
assert_equal 9 , wealth_column . precision
assert_equal 7 , wealth_column . scale
end
2005-07-04 18:51:02 +00:00
def test_native_types
Person . delete_all
Person . connection . add_column " people " , " last_name " , :string
Person . connection . add_column " people " , " bio " , :text
Person . connection . add_column " people " , " age " , :integer
Person . connection . add_column " people " , " height " , :float
2006-07-08 20:35:56 +00:00
Person . connection . add_column " people " , " wealth " , :decimal , :precision = > '30' , :scale = > '10'
2005-07-04 18:51:02 +00:00
Person . connection . add_column " people " , " birthday " , :datetime
Person . connection . add_column " people " , " favorite_day " , :date
2007-03-04 04:33:55 +00:00
Person . connection . add_column " people " , " moment_of_truth " , :datetime
2005-07-04 18:51:02 +00:00
Person . connection . add_column " people " , " male " , :boolean
2007-09-22 18:23:30 +00:00
Person . reset_column_information
2006-07-07 10:48:43 +00:00
2007-03-06 00:49:11 +00:00
assert_nothing_raised do
Person . create :first_name = > 'bob' , :last_name = > 'bobsen' ,
:bio = > " I was born .... " , :age = > 18 , :height = > 1 . 78 ,
:wealth = > BigDecimal . new ( " 12345678901234567890.0123456789 " ) ,
:birthday = > 18 . years . ago , :favorite_day = > 10 . days . ago ,
2007-11-24 04:59:21 +00:00
:moment_of_truth = > " 1782-10-10 21:40:18 " , :male = > true
2007-03-06 00:49:11 +00:00
end
bob = Person . find ( :first )
2006-07-08 20:35:56 +00:00
assert_equal 'bob' , bob . first_name
assert_equal 'bobsen' , bob . last_name
assert_equal " I was born .... " , bob . bio
assert_equal 18 , bob . age
# Test for 30 significent digits (beyond the 16 of float), 10 of them
# after the decimal place.
2008-01-18 07:30:42 +00:00
2007-05-18 01:14:18 +00:00
unless current_adapter? ( :SQLite3Adapter )
assert_equal BigDecimal . new ( " 0012345678901234567890.0123456789 " ) , bob . wealth
end
2008-01-18 07:30:42 +00:00
2006-07-08 20:35:56 +00:00
assert_equal true , bob . male?
2006-07-07 10:48:43 +00:00
2005-07-04 18:51:02 +00:00
assert_equal String , bob . first_name . class
assert_equal String , bob . last_name . class
assert_equal String , bob . bio . class
assert_equal Fixnum , bob . age . class
assert_equal Time , bob . birthday . class
2005-10-28 07:40:28 +00:00
2008-11-19 16:09:44 +00:00
if current_adapter? ( :OracleAdapter , :SybaseAdapter )
2006-07-10 18:24:35 +00:00
# Sybase, and Oracle don't differentiate between date/time
2005-10-28 07:40:28 +00:00
assert_equal Time , bob . favorite_day . class
else
assert_equal Date , bob . favorite_day . class
end
2007-03-09 00:34:17 +00:00
# Test DateTime column and defaults, including timezone.
2007-03-16 08:26:45 +00:00
# FIXME: moment of truth may be Time on 64-bit platforms.
2007-03-16 08:25:37 +00:00
if bob . moment_of_truth . is_a? ( DateTime )
2008-04-01 00:28:40 +00:00
with_env_tz 'US/Eastern' do
assert_equal DateTime . local_offset , bob . moment_of_truth . offset
assert_not_equal 0 , bob . moment_of_truth . offset
assert_not_equal " Z " , bob . moment_of_truth . zone
# US/Eastern is -5 hours from GMT
assert_equal Rational ( - 5 , 24 ) , bob . moment_of_truth . offset
2008-05-22 10:19:10 +00:00
assert_match / \ A-05:?00 \ Z / , bob . moment_of_truth . zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM
2008-04-01 00:28:40 +00:00
assert_equal DateTime :: ITALY , bob . moment_of_truth . start
end
2007-03-16 08:25:37 +00:00
end
2007-03-09 00:34:17 +00:00
2005-07-04 18:51:02 +00:00
assert_equal TrueClass , bob . male? . class
2006-07-08 20:35:56 +00:00
assert_kind_of BigDecimal , bob . wealth
2005-07-04 18:51:02 +00:00
end
2007-05-25 21:21:41 +00:00
if current_adapter? ( :MysqlAdapter )
def test_unabstracted_database_dependent_types
Person . delete_all
ActiveRecord :: Migration . add_column :people , :intelligence_quotient , :tinyint
2007-09-22 22:33:51 +00:00
Person . reset_column_information
2008-08-26 10:06:49 +00:00
assert_match / tinyint / , Person . columns_hash [ 'intelligence_quotient' ] . sql_type
2007-05-25 21:21:41 +00:00
ensure
2007-09-28 14:18:47 +00:00
ActiveRecord :: Migration . remove_column :people , :intelligence_quotient rescue nil
2007-05-25 21:21:41 +00:00
end
end
2005-09-28 17:50:28 +00:00
def test_add_remove_single_field_using_string_arguments
2005-07-04 18:51:02 +00:00
assert ! Person . column_methods_hash . include? ( :last_name )
2005-09-28 17:50:28 +00:00
ActiveRecord :: Migration . add_column 'people' , 'last_name' , :string
2005-07-04 18:51:02 +00:00
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
2006-07-07 10:48:43 +00:00
2005-09-28 17:50:28 +00:00
ActiveRecord :: Migration . remove_column 'people' , 'last_name'
Person . reset_column_information
assert ! Person . column_methods_hash . include? ( :last_name )
end
def test_add_remove_single_field_using_symbol_arguments
assert ! Person . column_methods_hash . include? ( :last_name )
ActiveRecord :: Migration . add_column :people , :last_name , :string
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
ActiveRecord :: Migration . remove_column :people , :last_name
2005-07-04 18:51:02 +00:00
Person . reset_column_information
assert ! Person . column_methods_hash . include? ( :last_name )
end
2006-07-07 10:48:43 +00:00
2005-07-05 07:19:20 +00:00
def test_add_rename
Person . delete_all
2006-07-07 10:48:43 +00:00
2005-07-05 07:19:20 +00:00
begin
2006-07-07 10:48:43 +00:00
Person . connection . add_column " people " , " girlfriend " , :string
2007-09-22 18:23:30 +00:00
Person . reset_column_information
2006-07-07 10:48:43 +00:00
Person . create :girlfriend = > 'bobette'
2005-07-05 07:19:20 +00:00
Person . connection . rename_column " people " , " girlfriend " , " exgirlfriend "
2006-07-07 10:48:43 +00:00
Person . reset_column_information
2005-07-05 07:19:20 +00:00
bob = Person . find ( :first )
2006-07-07 10:48:43 +00:00
2005-07-05 07:19:20 +00:00
assert_equal " bobette " , bob . exgirlfriend
ensure
Person . connection . remove_column ( " people " , " girlfriend " ) rescue nil
Person . connection . remove_column ( " people " , " exgirlfriend " ) rescue nil
end
2006-07-07 10:48:43 +00:00
2005-07-05 07:19:20 +00:00
end
2006-07-07 10:48:43 +00:00
2005-10-25 19:28:53 +00:00
def test_rename_column_using_symbol_arguments
begin
2007-09-22 18:23:30 +00:00
names_before = Person . find ( :all ) . map ( & :first_name )
2005-10-25 19:28:53 +00:00
Person . connection . rename_column :people , :first_name , :nick_name
Person . reset_column_information
assert Person . column_names . include? ( " nick_name " )
2007-09-22 18:23:30 +00:00
assert_equal names_before , Person . find ( :all ) . map ( & :nick_name )
2005-10-25 19:28:53 +00:00
ensure
Person . connection . remove_column ( " people " , " nick_name " )
Person . connection . add_column ( " people " , " first_name " , :string )
end
end
2006-07-07 10:48:43 +00:00
2005-10-25 19:28:53 +00:00
def test_rename_column
begin
2007-09-22 18:23:30 +00:00
names_before = Person . find ( :all ) . map ( & :first_name )
2005-10-25 19:28:53 +00:00
Person . connection . rename_column " people " , " first_name " , " nick_name "
Person . reset_column_information
assert Person . column_names . include? ( " nick_name " )
2007-09-22 18:23:30 +00:00
assert_equal names_before , Person . find ( :all ) . map ( & :nick_name )
2005-10-25 19:28:53 +00:00
ensure
Person . connection . remove_column ( " people " , " nick_name " )
Person . connection . add_column ( " people " , " first_name " , :string )
end
end
2008-06-21 23:18:30 +00:00
def test_rename_column_preserves_default_value_not_null
begin
default_before = Developer . connection . columns ( " developers " ) . find { | c | c . name == " salary " } . default
assert_equal 70000 , default_before
Developer . connection . rename_column " developers " , " salary " , " anual_salary "
Developer . reset_column_information
assert Developer . column_names . include? ( " anual_salary " )
default_after = Developer . connection . columns ( " developers " ) . find { | c | c . name == " anual_salary " } . default
assert_equal 70000 , default_after
ensure
Developer . connection . rename_column " developers " , " anual_salary " , " salary "
Developer . reset_column_information
end
end
def test_rename_nonexistent_column
ActiveRecord :: Base . connection . create_table ( :hats ) do | table |
table . column :hat_name , :string , :default = > nil
end
2008-07-14 06:40:05 +00:00
exception = if current_adapter? ( :PostgreSQLAdapter )
ActiveRecord :: StatementInvalid
else
ActiveRecord :: ActiveRecordError
end
assert_raises ( exception ) do
2008-06-21 23:18:30 +00:00
Person . connection . rename_column " hats " , " nonexistent " , " should_fail "
end
ensure
ActiveRecord :: Base . connection . drop_table ( :hats )
end
2006-07-07 10:48:43 +00:00
2007-05-29 07:21:41 +00:00
def test_rename_column_with_sql_reserved_word
begin
assert_nothing_raised { Person . connection . rename_column " people " , " first_name " , " group " }
Person . reset_column_information
assert Person . column_names . include? ( " group " )
ensure
Person . connection . remove_column ( " people " , " group " ) rescue nil
Person . connection . add_column ( " people " , " first_name " , :string ) rescue nil
end
end
2008-01-18 07:30:42 +00:00
2007-12-20 22:28:12 +00:00
def test_rename_column_with_an_index
ActiveRecord :: Base . connection . create_table ( :hats ) do | table |
table . column :hat_name , :string , :limit = > 100
table . column :hat_size , :integer
end
2008-02-15 20:12:45 +00:00
Person . connection . add_index :hats , :hat_name
2007-12-20 22:28:12 +00:00
assert_nothing_raised do
Person . connection . rename_column " hats " , " hat_name " , " name "
end
ensure
ActiveRecord :: Base . connection . drop_table ( :hats )
end
def test_remove_column_with_index
ActiveRecord :: Base . connection . create_table ( :hats ) do | table |
table . column :hat_name , :string , :limit = > 100
table . column :hat_size , :integer
end
ActiveRecord :: Base . connection . add_index " hats " , " hat_size "
assert_nothing_raised { Person . connection . remove_column ( " hats " , " hat_size " ) }
ensure
ActiveRecord :: Base . connection . drop_table ( :hats )
end
def test_remove_column_with_multi_column_index
ActiveRecord :: Base . connection . create_table ( :hats ) do | table |
table . column :hat_name , :string , :limit = > 100
table . column :hat_size , :integer
table . column :hat_style , :string , :limit = > 100
end
ActiveRecord :: Base . connection . add_index " hats " , [ " hat_style " , " hat_size " ] , :unique = > true
assert_nothing_raised { Person . connection . remove_column ( " hats " , " hat_size " ) }
ensure
ActiveRecord :: Base . connection . drop_table ( :hats )
end
2007-10-08 03:28:28 +00:00
def test_change_type_of_not_null_column
assert_nothing_raised do
Topic . connection . change_column " topics " , " written_on " , :datetime , :null = > false
Topic . reset_column_information
2008-01-18 07:30:42 +00:00
2007-10-08 03:28:28 +00:00
Topic . connection . change_column " topics " , " written_on " , :datetime , :null = > false
Topic . reset_column_information
end
end
2007-05-29 07:21:41 +00:00
2005-10-06 14:10:45 +00:00
def test_rename_table
begin
ActiveRecord :: Base . connection . create_table :octopuses do | t |
t . column :url , :string
2005-10-29 18:40:49 +00:00
end
2005-10-06 14:10:45 +00:00
ActiveRecord :: Base . connection . rename_table :octopuses , :octopi
2005-10-29 18:40:49 +00:00
2006-07-08 17:13:21 +00:00
# Using explicit id in insert for compatibility across all databases
2008-01-18 07:30:42 +00:00
con = ActiveRecord :: Base . connection
2007-01-05 00:12:06 +00:00
con . enable_identity_insert ( " octopi " , true ) if current_adapter? ( :SybaseAdapter )
2006-07-10 18:24:35 +00:00
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') " }
2007-01-05 00:12:06 +00:00
con . enable_identity_insert ( " octopi " , false ) if current_adapter? ( :SybaseAdapter )
2005-10-06 14:10:45 +00:00
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg' , ActiveRecord :: Base . connection . select_value ( " SELECT url FROM octopi WHERE id=1 " )
2005-10-29 18:40:49 +00:00
2005-10-06 14:10:45 +00:00
ensure
ActiveRecord :: Base . connection . drop_table :octopuses rescue nil
ActiveRecord :: Base . connection . drop_table :octopi rescue nil
end
end
2008-01-18 07:30:42 +00:00
2007-10-07 04:52:09 +00:00
def test_change_column_nullability
2008-01-18 07:30:42 +00:00
Person . delete_all
2007-10-07 04:52:09 +00:00
Person . connection . add_column " people " , " funny " , :boolean
Person . reset_column_information
assert Person . columns_hash [ " funny " ] . null , " Column 'funny' must initially allow nulls "
Person . connection . change_column " people " , " funny " , :boolean , :null = > false , :default = > true
Person . reset_column_information
assert ! Person . columns_hash [ " funny " ] . null , " Column 'funny' must *not* allow nulls at this point "
Person . connection . change_column " people " , " funny " , :boolean , :null = > true
Person . reset_column_information
assert Person . columns_hash [ " funny " ] . null , " Column 'funny' must allow nulls again at this point "
end
2005-10-29 18:40:49 +00:00
2006-10-09 02:14:36 +00:00
def test_rename_table_with_an_index
begin
ActiveRecord :: Base . connection . create_table :octopuses do | t |
t . column :url , :string
end
ActiveRecord :: Base . connection . add_index :octopuses , :url
2008-01-18 07:30:42 +00:00
2006-10-09 02:14:36 +00:00
ActiveRecord :: Base . connection . rename_table :octopuses , :octopi
# Using explicit id in insert for compatibility across all databases
2008-01-18 07:30:42 +00:00
con = ActiveRecord :: Base . connection
2007-01-05 00:12:06 +00:00
con . enable_identity_insert ( " octopi " , true ) if current_adapter? ( :SybaseAdapter )
2006-10-09 02:14:36 +00:00
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') " }
2007-01-05 00:12:06 +00:00
con . enable_identity_insert ( " octopi " , false ) if current_adapter? ( :SybaseAdapter )
2006-10-09 02:14:36 +00:00
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg' , ActiveRecord :: Base . connection . select_value ( " SELECT url FROM octopi WHERE id=1 " )
assert ActiveRecord :: Base . connection . indexes ( :octopi ) . first . columns . include? ( " url " )
ensure
ActiveRecord :: Base . connection . drop_table :octopuses rescue nil
ActiveRecord :: Base . connection . drop_table :octopi rescue nil
end
end
2005-07-05 07:19:20 +00:00
def test_change_column
2005-12-20 21:43:47 +00:00
Person . connection . add_column 'people' , 'age' , :integer
old_columns = Person . connection . columns ( Person . table_name , " #{ name } Columns " )
assert old_columns . find { | c | c . name == 'age' and c . type == :integer }
assert_nothing_raised { Person . connection . change_column " people " , " age " , :string }
2006-07-07 10:48:43 +00:00
2005-12-20 21:43:47 +00:00
new_columns = Person . connection . columns ( Person . table_name , " #{ name } Columns " )
assert_nil new_columns . find { | c | c . name == 'age' and c . type == :integer }
assert new_columns . find { | c | c . name == 'age' and c . type == :string }
2006-05-14 18:37:22 +00:00
old_columns = Topic . connection . columns ( Topic . table_name , " #{ name } Columns " )
assert old_columns . find { | c | c . name == 'approved' and c . type == :boolean and c . default == true }
assert_nothing_raised { Topic . connection . change_column :topics , :approved , :boolean , :default = > false }
2007-09-22 18:23:30 +00:00
new_columns = Topic . connection . columns ( Topic . table_name , " #{ name } Columns " )
2006-05-14 18:37:22 +00:00
assert_nil new_columns . find { | c | c . name == 'approved' and c . type == :boolean and c . default == true }
assert new_columns . find { | c | c . name == 'approved' and c . type == :boolean and c . default == false }
2006-05-21 15:13:28 +00:00
assert_nothing_raised { Topic . connection . change_column :topics , :approved , :boolean , :default = > true }
2006-07-07 10:48:43 +00:00
end
2008-01-18 07:30:42 +00:00
2007-01-15 02:22:53 +00:00
def test_change_column_with_nil_default
Person . connection . add_column " people " , " contributor " , :boolean , :default = > true
Person . reset_column_information
assert Person . new . contributor?
2008-01-18 07:30:42 +00:00
2007-01-15 02:22:53 +00:00
assert_nothing_raised { Person . connection . change_column " people " , " contributor " , :boolean , :default = > nil }
Person . reset_column_information
assert ! Person . new . contributor?
assert_nil Person . new . contributor
2007-01-29 22:06:08 +00:00
ensure
Person . connection . remove_column ( " people " , " contributor " ) rescue nil
2007-01-15 02:22:53 +00:00
end
2005-07-05 07:19:20 +00:00
def test_change_column_with_new_default
2007-01-15 01:24:23 +00:00
Person . connection . add_column " people " , " administrator " , :boolean , :default = > true
2006-07-07 10:48:43 +00:00
Person . reset_column_information
2005-07-05 07:19:20 +00:00
assert Person . new . administrator?
2006-07-07 10:48:43 +00:00
2007-01-15 01:24:23 +00:00
assert_nothing_raised { Person . connection . change_column " people " , " administrator " , :boolean , :default = > false }
2006-07-07 10:48:43 +00:00
Person . reset_column_information
2005-07-05 07:19:20 +00:00
assert ! Person . new . administrator?
2007-01-29 22:06:08 +00:00
ensure
Person . connection . remove_column ( " people " , " administrator " ) rescue nil
2006-07-07 10:48:43 +00:00
end
2008-01-18 07:30:42 +00:00
2007-01-15 01:24:23 +00:00
def test_change_column_default
Person . connection . change_column_default " people " , " first_name " , " Tester "
Person . reset_column_information
assert_equal " Tester " , Person . new . first_name
end
2007-10-15 07:33:53 +00:00
def test_change_column_quotes_column_names
Person . connection . create_table :testings do | t |
t . column :select , :string
end
assert_nothing_raised { Person . connection . change_column :testings , :select , :string , :limit = > 10 }
assert_nothing_raised { Person . connection . execute " insert into testings ( #{ Person . connection . quote_column_name ( 'select' ) } ) values ('7 chars') " }
ensure
Person . connection . drop_table :testings rescue nil
end
2008-07-14 06:42:20 +00:00
def test_keeping_default_and_notnull_constaint_on_change
Person . connection . create_table :testings do | t |
t . column :title , :string
end
person_klass = Class . new ( Person )
person_klass . set_table_name 'testings'
person_klass . connection . add_column " testings " , " wealth " , :integer , :null = > false , :default = > 99
person_klass . reset_column_information
assert_equal 99 , person_klass . columns_hash [ " wealth " ] . default
assert_equal false , person_klass . columns_hash [ " wealth " ] . null
assert_nothing_raised { person_klass . connection . execute ( " insert into testings (title) values ('tester') " ) }
# change column default to see that column doesn't lose its not null definition
person_klass . connection . change_column_default " testings " , " wealth " , 100
person_klass . reset_column_information
assert_equal 100 , person_klass . columns_hash [ " wealth " ] . default
assert_equal false , person_klass . columns_hash [ " wealth " ] . null
# rename column to see that column doesn't lose its not null and/or default definition
person_klass . connection . rename_column " testings " , " wealth " , " money "
person_klass . reset_column_information
assert_nil person_klass . columns_hash [ " wealth " ]
assert_equal 100 , person_klass . columns_hash [ " money " ] . default
assert_equal false , person_klass . columns_hash [ " money " ] . null
# change column
person_klass . connection . change_column " testings " , " money " , :integer , :null = > false , :default = > 1000
person_klass . reset_column_information
assert_equal 1000 , person_klass . columns_hash [ " money " ] . default
assert_equal false , person_klass . columns_hash [ " money " ] . null
# change column, make it nullable and clear default
person_klass . connection . change_column " testings " , " money " , :integer , :null = > true , :default = > nil
person_klass . reset_column_information
assert_nil person_klass . columns_hash [ " money " ] . default
assert_equal true , person_klass . columns_hash [ " money " ] . null
# change_column_null, make it not nullable and set null values to a default value
person_klass . connection . execute ( 'UPDATE testings SET money = NULL' )
person_klass . connection . change_column_null " testings " , " money " , false , 2000
person_klass . reset_column_information
assert_nil person_klass . columns_hash [ " money " ] . default
assert_equal false , person_klass . columns_hash [ " money " ] . null
assert_equal [ 2000 ] , Person . connection . select_values ( " SELECT money FROM testings " ) . map { | s | s . to_i } . sort
ensure
Person . connection . drop_table :testings rescue nil
end
2007-01-15 01:24:23 +00:00
def test_change_column_default_to_null
Person . connection . change_column_default " people " , " first_name " , nil
Person . reset_column_information
assert_nil Person . new . first_name
end
2005-07-04 18:51:02 +00:00
def test_add_table
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2006-07-07 10:48:43 +00:00
2005-07-04 18:51:02 +00:00
WeNeedReminders . up
2008-01-18 07:30:42 +00:00
assert Reminder . create ( " content " = > " hello world " , " remind_at " = > Time . now )
2005-07-04 18:51:02 +00:00
assert_equal " hello world " , Reminder . find ( :first ) . content
2006-07-07 10:48:43 +00:00
2005-07-04 18:51:02 +00:00
WeNeedReminders . down
assert_raises ( ActiveRecord :: StatementInvalid ) { Reminder . find ( :first ) }
end
2006-07-08 20:35:56 +00:00
def test_add_table_with_decimals
Person . connection . drop_table :big_numbers rescue nil
assert ! BigNumber . table_exists?
GiveMeBigNumbers . up
assert BigNumber . create (
:bank_balance = > 1586 . 43 ,
:big_bank_balance = > BigDecimal ( " 1000234000567.95 " ) ,
:world_population = > 6000000000 ,
:my_house_population = > 3 ,
:value_of_e = > BigDecimal ( " 2.7182818284590452353602875 " )
)
b = BigNumber . find ( :first )
assert_not_nil b
assert_not_nil b . bank_balance
assert_not_nil b . big_bank_balance
assert_not_nil b . world_population
assert_not_nil b . my_house_population
assert_not_nil b . value_of_e
# TODO: set world_population >= 2**62 to cover 64-bit platforms and test
# is_a?(Bignum)
assert_kind_of Integer , b . world_population
assert_equal 6000000000 , b . world_population
assert_kind_of Fixnum , b . my_house_population
assert_equal 3 , b . my_house_population
assert_kind_of BigDecimal , b . bank_balance
assert_equal BigDecimal ( " 1586.43 " ) , b . bank_balance
assert_kind_of BigDecimal , b . big_bank_balance
assert_equal BigDecimal ( " 1000234000567.95 " ) , b . big_bank_balance
# This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
2007-09-28 14:18:47 +00:00
# precision/scale explicitly left out. By the SQL standard, numbers
2006-07-08 20:35:56 +00:00
# assigned to this field should be truncated but that's seldom respected.
if current_adapter? ( :PostgreSQLAdapter , :SQLite2Adapter )
# - PostgreSQL changes the SQL spec on columns declared simply as
# "decimal" to something more useful: instead of being given a scale
# of 0, they take on the compile-time limit for precision and scale,
# so the following should succeed unless you have used really wacky
# compilation options
# - SQLite2 has the default behavior of preserving all data sent in,
# so this happens there too
assert_kind_of BigDecimal , b . value_of_e
assert_equal BigDecimal ( " 2.7182818284590452353602875 " ) , b . value_of_e
elsif current_adapter? ( :SQLiteAdapter )
# - SQLite3 stores a float, in violation of SQL
assert_kind_of BigDecimal , b . value_of_e
assert_equal BigDecimal ( " 2.71828182845905 " ) , b . value_of_e
else
# - SQL standard is an integer
assert_kind_of Fixnum , b . value_of_e
assert_equal 2 , b . value_of_e
end
GiveMeBigNumbers . down
assert_raises ( ActiveRecord :: StatementInvalid ) { BigNumber . find ( :first ) }
end
2005-07-04 18:51:02 +00:00
def test_migrator
assert ! Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-07-04 18:51:02 +00:00
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " )
2005-07-04 18:51:02 +00:00
2005-07-05 07:19:20 +00:00
assert_equal 3 , ActiveRecord :: Migrator . current_version
2005-07-04 18:51:02 +00:00
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
assert Reminder . create ( " content " = > " hello world " , " remind_at " = > Time . now )
assert_equal " hello world " , Reminder . find ( :first ) . content
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /valid " )
2005-07-04 18:51:02 +00:00
assert_equal 0 , ActiveRecord :: Migrator . current_version
Person . reset_column_information
assert ! Person . column_methods_hash . include? ( :last_name )
assert_raises ( ActiveRecord :: StatementInvalid ) { Reminder . find ( :first ) }
end
def test_migrator_one_up
assert ! Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2006-07-07 10:48:43 +00:00
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
2005-07-04 18:51:02 +00:00
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-07-04 18:51:02 +00:00
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 2 )
2005-07-04 18:51:02 +00:00
assert Reminder . create ( " content " = > " hello world " , " remind_at " = > Time . now )
assert_equal " hello world " , Reminder . find ( :first ) . content
end
2006-07-07 10:48:43 +00:00
2005-07-04 18:51:02 +00:00
def test_migrator_one_down
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " )
2008-03-28 21:21:01 +00:00
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /valid " , 1 )
2008-03-28 21:21:01 +00:00
2005-07-04 18:51:02 +00:00
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-07-04 18:51:02 +00:00
end
2006-07-07 10:48:43 +00:00
2005-07-04 18:51:02 +00:00
def test_migrator_one_up_one_down
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /valid " , 0 )
2005-07-04 18:51:02 +00:00
assert ! Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-07-04 18:51:02 +00:00
end
2006-07-07 10:48:43 +00:00
2008-06-13 14:14:07 +00:00
def test_migrator_double_up
assert_equal ( 0 , ActiveRecord :: Migrator . current_version )
ActiveRecord :: Migrator . run ( :up , MIGRATIONS_ROOT + " /valid " , 1 )
assert_nothing_raised { ActiveRecord :: Migrator . run ( :up , MIGRATIONS_ROOT + " /valid " , 1 ) }
assert_equal ( 1 , ActiveRecord :: Migrator . current_version )
end
def test_migrator_double_down
assert_equal ( 0 , ActiveRecord :: Migrator . current_version )
ActiveRecord :: Migrator . run ( :up , MIGRATIONS_ROOT + " /valid " , 1 )
ActiveRecord :: Migrator . run ( :down , MIGRATIONS_ROOT + " /valid " , 1 )
assert_nothing_raised { ActiveRecord :: Migrator . run ( :down , MIGRATIONS_ROOT + " /valid " , 1 ) }
assert_equal ( 0 , ActiveRecord :: Migrator . current_version )
end
2008-08-22 20:53:31 +00:00
if current_adapter? ( :PostgreSQLAdapter )
def test_migrator_one_up_with_exception_and_rollback
assert ! Person . column_methods_hash . include? ( :last_name )
e = assert_raises ( StandardError ) do
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /broken " , 100 )
end
assert_equal " An error has occurred, this and all later migrations canceled: \n \n Something broke " , e . message
Person . reset_column_information
assert ! Person . column_methods_hash . include? ( :last_name )
end
end
2008-04-09 16:20:15 +00:00
def test_finds_migrations
migrations = ActiveRecord :: Migrator . new ( :up , MIGRATIONS_ROOT + " /valid " ) . migrations
[ [ '1' , 'people_have_last_names' ] ,
[ '2' , 'we_need_reminders' ] ,
[ '3' , 'innocent_jointable' ] ] . each_with_index do | pair , i |
migrations [ i ] . version == pair . first
migrations [ 1 ] . name == pair . last
end
end
def test_finds_pending_migrations
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /interleaved/pass_2 " , 1 )
migrations = ActiveRecord :: Migrator . new ( :up , MIGRATIONS_ROOT + " /interleaved/pass_2 " ) . pending_migrations
assert_equal 1 , migrations . size
migrations [ 0 ] . version == '3'
migrations [ 0 ] . name == 'innocent_jointable'
end
2008-08-02 05:44:02 +00:00
def test_only_loads_pending_migrations
# migrate up to 1
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
# now unload the migrations that have been defined
PeopleHaveLastNames . unloadable
ActiveSupport :: Dependencies . remove_unloadable_constants!
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /valid " , nil )
assert ! defined? PeopleHaveLastNames
%w( WeNeedReminders, InnocentJointable ) . each do | migration |
assert defined? migration
end
ensure
load ( MIGRATIONS_ROOT + " /valid/1_people_have_last_names.rb " )
end
2008-04-09 16:20:15 +00:00
def test_migrator_interleaved_migrations
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /interleaved/pass_1 " )
assert_nothing_raised do
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /interleaved/pass_2 " )
end
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
assert_nothing_raised do
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /interleaved/pass_3 " )
end
end
2008-04-17 18:43:47 +00:00
def test_migrator_db_has_no_schema_migrations_table
ActiveRecord :: Base . connection . execute ( " DROP TABLE schema_migrations; " )
assert_nothing_raised do
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /valid " , 1 )
end
end
2006-03-04 18:46:51 +00:00
def test_migrator_verbosity
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
2006-03-04 18:46:51 +00:00
assert PeopleHaveLastNames . message_count > 0
PeopleHaveLastNames . message_count = 0
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /valid " , 0 )
2006-03-04 18:46:51 +00:00
assert PeopleHaveLastNames . message_count > 0
PeopleHaveLastNames . message_count = 0
end
2006-07-07 10:48:43 +00:00
2006-03-04 18:46:51 +00:00
def test_migrator_verbosity_off
PeopleHaveLastNames . verbose = false
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
2006-03-04 18:46:51 +00:00
assert PeopleHaveLastNames . message_count . zero?
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . down ( MIGRATIONS_ROOT + " /valid " , 0 )
2006-03-04 18:46:51 +00:00
assert PeopleHaveLastNames . message_count . zero?
end
2006-07-07 10:48:43 +00:00
2005-07-09 15:46:29 +00:00
def test_migrator_going_down_due_to_version_target
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . up ( MIGRATIONS_ROOT + " /valid " , 1 )
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /valid " , 0 )
2005-07-09 15:46:29 +00:00
assert ! Person . column_methods_hash . include? ( :last_name )
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-07-09 15:46:29 +00:00
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /valid " )
2005-07-09 15:46:29 +00:00
Person . reset_column_information
assert Person . column_methods_hash . include? ( :last_name )
assert Reminder . create ( " content " = > " hello world " , " remind_at " = > Time . now )
assert_equal " hello world " , Reminder . find ( :first ) . content
end
2008-03-28 21:21:01 +00:00
def test_migrator_rollback
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /valid " )
assert_equal ( 3 , ActiveRecord :: Migrator . current_version )
ActiveRecord :: Migrator . rollback ( MIGRATIONS_ROOT + " /valid " )
2008-04-09 16:20:15 +00:00
assert_equal ( 2 , ActiveRecord :: Migrator . current_version )
2008-03-28 21:21:01 +00:00
ActiveRecord :: Migrator . rollback ( MIGRATIONS_ROOT + " /valid " )
2008-04-09 16:20:15 +00:00
assert_equal ( 1 , ActiveRecord :: Migrator . current_version )
2008-03-28 21:21:01 +00:00
ActiveRecord :: Migrator . rollback ( MIGRATIONS_ROOT + " /valid " )
2008-04-09 16:20:15 +00:00
assert_equal ( 0 , ActiveRecord :: Migrator . current_version )
2008-03-28 21:21:01 +00:00
ActiveRecord :: Migrator . rollback ( MIGRATIONS_ROOT + " /valid " )
2008-04-09 16:20:15 +00:00
assert_equal ( 0 , ActiveRecord :: Migrator . current_version )
2008-03-28 21:21:01 +00:00
end
2005-09-26 21:30:12 +00:00
2008-04-09 16:20:15 +00:00
def test_schema_migrations_table_name
2005-09-26 21:30:12 +00:00
ActiveRecord :: Base . table_name_prefix = " prefix_ "
ActiveRecord :: Base . table_name_suffix = " _suffix "
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2008-04-09 16:20:15 +00:00
assert_equal " prefix_schema_migrations_suffix " , ActiveRecord :: Migrator . schema_migrations_table_name
2005-09-26 21:30:12 +00:00
ActiveRecord :: Base . table_name_prefix = " "
ActiveRecord :: Base . table_name_suffix = " "
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2008-04-09 16:20:15 +00:00
assert_equal " schema_migrations " , ActiveRecord :: Migrator . schema_migrations_table_name
2005-11-12 11:59:54 +00:00
ensure
ActiveRecord :: Base . table_name_prefix = " "
ActiveRecord :: Base . table_name_suffix = " "
2005-09-26 21:30:12 +00:00
end
2006-07-07 10:48:43 +00:00
2005-09-26 21:30:12 +00:00
def test_proper_table_name
assert_equal " table " , ActiveRecord :: Migrator . proper_table_name ( 'table' )
assert_equal " table " , ActiveRecord :: Migrator . proper_table_name ( :table )
assert_equal " reminders " , ActiveRecord :: Migrator . proper_table_name ( Reminder )
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2005-09-26 21:30:12 +00:00
assert_equal Reminder . table_name , ActiveRecord :: Migrator . proper_table_name ( Reminder )
2006-07-07 10:48:43 +00:00
2005-09-26 21:30:12 +00:00
# Use the model's own prefix/suffix if a model is given
ActiveRecord :: Base . table_name_prefix = " ARprefix_ "
ActiveRecord :: Base . table_name_suffix = " _ARsuffix "
Reminder . table_name_prefix = 'prefix_'
Reminder . table_name_suffix = '_suffix'
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2005-09-26 21:30:12 +00:00
assert_equal " prefix_reminders_suffix " , ActiveRecord :: Migrator . proper_table_name ( Reminder )
Reminder . table_name_prefix = ''
Reminder . table_name_suffix = ''
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2006-07-07 10:48:43 +00:00
# Use AR::Base's prefix/suffix if string or symbol is given
2005-09-26 21:30:12 +00:00
ActiveRecord :: Base . table_name_prefix = " prefix_ "
ActiveRecord :: Base . table_name_suffix = " _suffix "
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2005-09-26 21:30:12 +00:00
assert_equal " prefix_table_suffix " , ActiveRecord :: Migrator . proper_table_name ( 'table' )
assert_equal " prefix_table_suffix " , ActiveRecord :: Migrator . proper_table_name ( :table )
ActiveRecord :: Base . table_name_prefix = " "
ActiveRecord :: Base . table_name_suffix = " "
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2006-07-07 10:48:43 +00:00
end
2005-09-26 21:30:12 +00:00
def test_add_drop_table_with_prefix_and_suffix
2005-10-28 07:40:28 +00:00
assert ! Reminder . table_exists?
2005-09-26 21:30:12 +00:00
ActiveRecord :: Base . table_name_prefix = 'prefix_'
ActiveRecord :: Base . table_name_suffix = '_suffix'
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2005-11-12 11:59:54 +00:00
Reminder . reset_sequence_name
2005-09-26 21:30:12 +00:00
WeNeedReminders . up
assert Reminder . create ( " content " = > " hello world " , " remind_at " = > Time . now )
assert_equal " hello world " , Reminder . find ( :first ) . content
WeNeedReminders . down
assert_raises ( ActiveRecord :: StatementInvalid ) { Reminder . find ( :first ) }
2005-11-12 11:59:54 +00:00
ensure
2005-09-26 21:30:12 +00:00
ActiveRecord :: Base . table_name_prefix = ''
ActiveRecord :: Base . table_name_suffix = ''
2005-10-10 18:59:56 +00:00
Reminder . reset_table_name
2005-11-12 11:59:54 +00:00
Reminder . reset_sequence_name
2005-09-26 21:30:12 +00:00
end
2005-11-12 11:59:54 +00:00
2007-01-29 22:06:08 +00:00
def test_create_table_with_binary_column
Person . connection . drop_table :binary_testings rescue nil
2006-07-07 10:48:43 +00:00
2007-01-29 22:06:08 +00:00
assert_nothing_raised {
Person . connection . create_table :binary_testings do | t |
t . column " data " , :binary , :null = > false
end
}
2006-07-07 10:48:43 +00:00
2007-01-29 22:06:08 +00:00
columns = Person . connection . columns ( :binary_testings )
data_column = columns . detect { | c | c . name == " data " }
2006-04-04 16:33:31 +00:00
2008-09-14 11:06:10 +00:00
if current_adapter? ( :MysqlAdapter )
assert_equal '' , data_column . default
else
assert_nil data_column . default
end
2006-04-04 16:33:31 +00:00
2007-01-29 22:06:08 +00:00
Person . connection . drop_table :binary_testings rescue nil
2006-03-25 23:09:52 +00:00
end
2007-01-29 22:06:08 +00:00
2005-10-31 15:43:02 +00:00
def test_migrator_with_duplicates
assert_raises ( ActiveRecord :: DuplicateMigrationVersionError ) do
2008-01-21 17:20:51 +00:00
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /duplicate " , nil )
2005-10-31 15:43:02 +00:00
end
end
2006-08-23 05:49:40 +00:00
2008-05-07 05:59:34 +00:00
def test_migrator_with_duplicate_names
assert_raises ( ActiveRecord :: DuplicateMigrationNameError , " Multiple migrations have the name Chunky " ) do
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /duplicate_names " , nil )
end
end
2006-08-23 05:49:40 +00:00
def test_migrator_with_missing_version_numbers
2008-03-28 21:21:01 +00:00
assert_raise ( ActiveRecord :: UnknownMigrationVersionError ) do
ActiveRecord :: Migrator . migrate ( MIGRATIONS_ROOT + " /missing " , 500 )
end
2006-08-23 05:49:40 +00:00
end
2007-09-13 23:21:14 +00:00
2007-01-15 00:34:43 +00:00
def test_create_table_with_custom_sequence_name
return unless current_adapter? :OracleAdapter
# table name is 29 chars, the standard sequence name will
# be 33 chars and fail
assert_raises ( ActiveRecord :: StatementInvalid ) do
begin
Person . connection . create_table :table_with_name_thats_just_ok do | t |
t . column :foo , :string , :null = > false
end
ensure
Person . connection . drop_table :table_with_name_thats_just_ok rescue nil
end
end
# should be all good w/ a custom sequence name
assert_nothing_raised do
begin
Person . connection . create_table :table_with_name_thats_just_ok ,
:sequence_name = > 'suitably_short_seq' do | t |
t . column :foo , :string , :null = > false
end
Person . connection . execute ( " select suitably_short_seq.nextval from dual " )
ensure
Person . connection . drop_table :table_with_name_thats_just_ok ,
:sequence_name = > 'suitably_short_seq' rescue nil
end
end
# confirm the custom sequence got dropped
assert_raises ( ActiveRecord :: StatementInvalid ) do
Person . connection . execute ( " select suitably_short_seq.nextval from dual " )
end
end
2008-04-01 00:28:40 +00:00
protected
def with_env_tz ( new_tz = 'US/Eastern' )
old_tz , ENV [ 'TZ' ] = ENV [ 'TZ' ] , new_tz
yield
ensure
old_tz ? ENV [ 'TZ' ] = old_tz : ENV . delete ( 'TZ' )
end
2005-10-28 07:40:28 +00:00
end
2008-04-17 18:43:47 +00:00
2007-10-19 02:09:06 +00:00
uses_mocha 'Sexy migration tests' do
2008-01-21 17:20:51 +00:00
class SexyMigrationsTest < ActiveRecord :: TestCase
2007-10-19 02:09:06 +00:00
def test_references_column_type_adds_id
with_new_table do | t |
t . expects ( :column ) . with ( 'customer_id' , :integer , { } )
t . references :customer
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:51:44 +00:00
def test_references_column_type_with_polymorphic_adds_type
2007-10-19 02:09:06 +00:00
with_new_table do | t |
t . expects ( :column ) . with ( 'taggable_type' , :string , { } )
t . expects ( :column ) . with ( 'taggable_id' , :integer , { } )
t . references :taggable , :polymorphic = > true
end
end
2008-01-18 07:30:42 +00:00
2008-01-11 19:54:19 +00:00
def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
with_new_table do | t |
t . expects ( :column ) . with ( 'taggable_type' , :string , { :null = > false } )
t . expects ( :column ) . with ( 'taggable_id' , :integer , { :null = > false } )
t . references :taggable , :polymorphic = > true , :null = > false
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:09:06 +00:00
def test_belongs_to_works_like_references
with_new_table do | t |
t . expects ( :column ) . with ( 'customer_id' , :integer , { } )
t . belongs_to :customer
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:25:23 +00:00
def test_timestamps_creates_updated_at_and_created_at
with_new_table do | t |
2008-08-22 11:48:00 +00:00
t . expects ( :column ) . with ( :created_at , :datetime , kind_of ( Hash ) )
t . expects ( :column ) . with ( :updated_at , :datetime , kind_of ( Hash ) )
2007-10-19 02:25:23 +00:00
t . timestamps
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:25:23 +00:00
def test_integer_creates_integer_column
with_new_table do | t |
t . expects ( :column ) . with ( :foo , 'integer' , { } )
t . expects ( :column ) . with ( :bar , 'integer' , { } )
t . integer :foo , :bar
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:25:23 +00:00
def test_string_creates_string_column
with_new_table do | t |
t . expects ( :column ) . with ( :foo , 'string' , { } )
t . expects ( :column ) . with ( :bar , 'string' , { } )
t . string :foo , :bar
end
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:09:06 +00:00
protected
def with_new_table
2008-05-03 16:29:47 +00:00
Person . connection . create_table :delete_me , :force = > true do | t |
2007-10-19 02:09:06 +00:00
yield t
end
ensure
Person . connection . drop_table :delete_me rescue nil
end
2008-01-18 07:30:42 +00:00
2007-10-19 02:09:06 +00:00
end # SexyMigrationsTest
end # uses_mocha
2008-05-03 16:29:47 +00:00
uses_mocha 'ChangeTable migration tests' do
class ChangeTableMigrationsTest < ActiveRecord :: TestCase
def setup
@connection = Person . connection
@connection . create_table :delete_me , :force = > true do | t |
end
end
def teardown
Person . connection . drop_table :delete_me rescue nil
end
def test_references_column_type_adds_id
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , 'customer_id' , :integer , { } )
t . references :customer
end
end
def test_remove_references_column_type_removes_id
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , 'customer_id' )
t . remove_references :customer
end
end
def test_add_belongs_to_works_like_add_references
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , 'customer_id' , :integer , { } )
t . belongs_to :customer
end
end
def test_remove_belongs_to_works_like_remove_references
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , 'customer_id' )
t . remove_belongs_to :customer
end
end
def test_references_column_type_with_polymorphic_adds_type
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , 'taggable_type' , :string , { } )
@connection . expects ( :add_column ) . with ( :delete_me , 'taggable_id' , :integer , { } )
t . references :taggable , :polymorphic = > true
end
end
def test_remove_references_column_type_with_polymorphic_removes_type
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , 'taggable_type' )
@connection . expects ( :remove_column ) . with ( :delete_me , 'taggable_id' )
t . remove_references :taggable , :polymorphic = > true
end
end
def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , 'taggable_type' , :string , { :null = > false } )
@connection . expects ( :add_column ) . with ( :delete_me , 'taggable_id' , :integer , { :null = > false } )
t . references :taggable , :polymorphic = > true , :null = > false
end
end
def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , 'taggable_type' )
@connection . expects ( :remove_column ) . with ( :delete_me , 'taggable_id' )
t . remove_references :taggable , :polymorphic = > true , :null = > false
end
end
def test_timestamps_creates_updated_at_and_created_at
with_change_table do | t |
@connection . expects ( :add_timestamps ) . with ( :delete_me )
t . timestamps
end
end
def test_remove_timestamps_creates_updated_at_and_created_at
with_change_table do | t |
@connection . expects ( :remove_timestamps ) . with ( :delete_me )
t . remove_timestamps
end
end
def string_column
if current_adapter? ( :PostgreSQLAdapter )
" character varying(255) "
else
'varchar(255)'
end
end
def integer_column
2008-06-27 08:06:33 +00:00
if current_adapter? ( :MysqlAdapter )
2008-05-03 16:29:47 +00:00
'int(11)'
2008-06-27 08:06:33 +00:00
else
'integer'
2008-05-03 16:29:47 +00:00
end
end
def test_integer_creates_integer_column
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , :foo , integer_column , { } )
@connection . expects ( :add_column ) . with ( :delete_me , :bar , integer_column , { } )
t . integer :foo , :bar
end
end
def test_string_creates_string_column
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , :foo , string_column , { } )
@connection . expects ( :add_column ) . with ( :delete_me , :bar , string_column , { } )
t . string :foo , :bar
end
end
def test_column_creates_column
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , :bar , :integer , { } )
t . column :bar , :integer
end
end
def test_column_creates_column_with_options
with_change_table do | t |
@connection . expects ( :add_column ) . with ( :delete_me , :bar , :integer , { :null = > false } )
t . column :bar , :integer , :null = > false
end
end
def test_index_creates_index
with_change_table do | t |
@connection . expects ( :add_index ) . with ( :delete_me , :bar , { } )
t . index :bar
end
end
def test_index_creates_index_with_options
with_change_table do | t |
@connection . expects ( :add_index ) . with ( :delete_me , :bar , { :unique = > true } )
t . index :bar , :unique = > true
end
end
def test_change_changes_column
with_change_table do | t |
@connection . expects ( :change_column ) . with ( :delete_me , :bar , :string , { } )
t . change :bar , :string
end
end
def test_change_changes_column_with_options
with_change_table do | t |
@connection . expects ( :change_column ) . with ( :delete_me , :bar , :string , { :null = > true } )
t . change :bar , :string , :null = > true
end
end
def test_change_default_changes_column
with_change_table do | t |
@connection . expects ( :change_column_default ) . with ( :delete_me , :bar , :string )
t . change_default :bar , :string
end
end
def test_remove_drops_single_column
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , [ :bar ] )
t . remove :bar
end
end
def test_remove_drops_multiple_columns
with_change_table do | t |
@connection . expects ( :remove_column ) . with ( :delete_me , [ :bar , :baz ] )
t . remove :bar , :baz
end
end
def test_remove_index_removes_index_with_options
with_change_table do | t |
@connection . expects ( :remove_index ) . with ( :delete_me , { :unique = > true } )
t . remove_index :unique = > true
end
end
def test_rename_renames_column
with_change_table do | t |
@connection . expects ( :rename_column ) . with ( :delete_me , :bar , :baz )
t . rename :bar , :baz
end
end
protected
def with_change_table
Person . connection . change_table :delete_me do | t |
yield t
end
end
end # ChangeTable test
end # uses_mocha
2005-10-29 18:40:49 +00:00
end