1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activerecord/test/cases/migration/columns_test.rb
Sean Griffin 4d3e88fc75 Don't type cast the default on the column
If we want to have type decorators mess with the attribute, but not the
column, we need to stop type casting on the column. Where possible, we
changed the tests to test the value of `column_defaults`, which is
public API. `Column#default` is not.
2014-06-17 16:02:53 -06:00

296 lines
12 KiB
Ruby

require "cases/migration/helper"
module ActiveRecord
class Migration
class ColumnsTest < ActiveRecord::TestCase
include ActiveRecord::Migration::TestHelper
self.use_transactional_fixtures = false
# FIXME: this is more of an integration test with AR::Base and the
# schema modifications. Maybe we should move this?
def test_add_rename
add_column "test_models", "girlfriend", :string
TestModel.reset_column_information
TestModel.create :girlfriend => 'bobette'
rename_column "test_models", "girlfriend", "exgirlfriend"
TestModel.reset_column_information
bob = TestModel.first
assert_equal "bobette", bob.exgirlfriend
end
# FIXME: another integration test. We should decouple this from the
# AR::Base implementation.
def test_rename_column_using_symbol_arguments
add_column :test_models, :first_name, :string
TestModel.create :first_name => 'foo'
rename_column :test_models, :first_name, :nick_name
TestModel.reset_column_information
assert TestModel.column_names.include?("nick_name")
assert_equal ['foo'], TestModel.all.map(&:nick_name)
end
# FIXME: another integration test. We should decouple this from the
# AR::Base implementation.
def test_rename_column
add_column "test_models", "first_name", "string"
TestModel.create :first_name => 'foo'
rename_column "test_models", "first_name", "nick_name"
TestModel.reset_column_information
assert TestModel.column_names.include?("nick_name")
assert_equal ['foo'], TestModel.all.map(&:nick_name)
end
def test_rename_column_preserves_default_value_not_null
add_column 'test_models', 'salary', :integer, :default => 70000
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
assert_equal '70000', default_before
rename_column "test_models", "salary", "annual_salary"
assert TestModel.column_names.include?("annual_salary")
default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
assert_equal '70000', default_after
end
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_mysql_rename_column_preserves_auto_increment
rename_column "test_models", "id", "id_test"
assert_equal "auto_increment", connection.columns("test_models").find { |c| c.name == "id_test" }.extra
end
end
def test_rename_nonexistent_column
exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
ActiveRecord::StatementInvalid
else
ActiveRecord::ActiveRecordError
end
assert_raise(exception) do
rename_column "test_models", "nonexistent", "should_fail"
end
end
def test_rename_column_with_sql_reserved_word
add_column 'test_models', 'first_name', :string
rename_column "test_models", "first_name", "group"
assert TestModel.column_names.include?("group")
end
def test_rename_column_with_an_index
add_column "test_models", :hat_name, :string
add_index :test_models, :hat_name
assert_equal 1, connection.indexes('test_models').size
rename_column "test_models", "hat_name", "name"
assert_equal ['index_test_models_on_name'], connection.indexes('test_models').map(&:name)
end
def test_rename_column_with_multi_column_index
add_column "test_models", :hat_size, :integer
add_column "test_models", :hat_style, :string, limit: 100
add_index "test_models", ["hat_style", "hat_size"], unique: true
rename_column "test_models", "hat_size", 'size'
if current_adapter? :OracleAdapter
assert_equal ['i_test_models_hat_style_size'], connection.indexes('test_models').map(&:name)
else
assert_equal ['index_test_models_on_hat_style_and_size'], connection.indexes('test_models').map(&:name)
end
rename_column "test_models", "hat_style", 'style'
if current_adapter? :OracleAdapter
assert_equal ['i_test_models_style_size'], connection.indexes('test_models').map(&:name)
else
assert_equal ['index_test_models_on_style_and_size'], connection.indexes('test_models').map(&:name)
end
end
def test_rename_column_does_not_rename_custom_named_index
add_column "test_models", :hat_name, :string
add_index :test_models, :hat_name, :name => 'idx_hat_name'
assert_equal 1, connection.indexes('test_models').size
rename_column "test_models", "hat_name", "name"
assert_equal ['idx_hat_name'], connection.indexes('test_models').map(&:name)
end
def test_remove_column_with_index
add_column "test_models", :hat_name, :string
add_index :test_models, :hat_name
assert_equal 1, connection.indexes('test_models').size
remove_column("test_models", "hat_name")
assert_equal 0, connection.indexes('test_models').size
end
def test_remove_column_with_multi_column_index
add_column "test_models", :hat_size, :integer
add_column "test_models", :hat_style, :string, :limit => 100
add_index "test_models", ["hat_style", "hat_size"], :unique => true
assert_equal 1, connection.indexes('test_models').size
remove_column("test_models", "hat_size")
# Every database and/or database adapter has their own behavior
# if it drops the multi-column index when any of the indexed columns dropped by remove_column.
if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
assert_equal [], connection.indexes('test_models').map(&:name)
else
assert_equal ['index_test_models_on_hat_style_and_hat_size'], connection.indexes('test_models').map(&:name)
end
end
def test_change_type_of_not_null_column
change_column "test_models", "updated_at", :datetime, :null => false
change_column "test_models", "updated_at", :datetime, :null => false
TestModel.reset_column_information
assert_equal false, TestModel.columns_hash['updated_at'].null
ensure
change_column "test_models", "updated_at", :datetime, :null => true
end
def test_change_column_nullability
add_column "test_models", "funny", :boolean
assert TestModel.columns_hash["funny"].null, "Column 'funny' must initially allow nulls"
change_column "test_models", "funny", :boolean, :null => false, :default => true
TestModel.reset_column_information
assert_not TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
change_column "test_models", "funny", :boolean, :null => true
TestModel.reset_column_information
assert TestModel.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point"
end
def test_change_column
add_column 'test_models', 'age', :integer
add_column 'test_models', 'approved', :boolean, :default => true
old_columns = connection.columns(TestModel.table_name)
assert old_columns.find { |c| c.name == 'age' && c.type == :integer }
change_column "test_models", "age", :string
new_columns = connection.columns(TestModel.table_name)
assert_not new_columns.find { |c| c.name == 'age' and c.type == :integer }
assert new_columns.find { |c| c.name == 'age' and c.type == :string }
old_columns = connection.columns(TestModel.table_name)
assert old_columns.find { |c|
default = c.type_cast_from_database(c.default)
c.name == 'approved' && c.type == :boolean && default == true
}
change_column :test_models, :approved, :boolean, :default => false
new_columns = connection.columns(TestModel.table_name)
assert_not new_columns.find { |c|
default = c.type_cast_from_database(c.default)
c.name == 'approved' and c.type == :boolean and default == true
}
assert new_columns.find { |c|
default = c.type_cast_from_database(c.default)
c.name == 'approved' and c.type == :boolean and default == false
}
change_column :test_models, :approved, :boolean, :default => true
end
def test_change_column_with_nil_default
add_column "test_models", "contributor", :boolean, :default => true
assert TestModel.new.contributor?
change_column "test_models", "contributor", :boolean, :default => nil
TestModel.reset_column_information
assert_not TestModel.new.contributor?
assert_nil TestModel.new.contributor
end
def test_change_column_with_new_default
add_column "test_models", "administrator", :boolean, :default => true
assert TestModel.new.administrator?
change_column "test_models", "administrator", :boolean, :default => false
TestModel.reset_column_information
assert_not TestModel.new.administrator?
end
def test_change_column_with_custom_index_name
add_column "test_models", "category", :string
add_index :test_models, :category, name: 'test_models_categories_idx'
assert_equal ['test_models_categories_idx'], connection.indexes('test_models').map(&:name)
change_column "test_models", "category", :string, null: false, default: 'article'
assert_equal ['test_models_categories_idx'], connection.indexes('test_models').map(&:name)
end
def test_change_column_with_long_index_name
table_name_prefix = 'test_models_'
long_index_name = table_name_prefix + ('x' * (connection.allowed_index_name_length - table_name_prefix.length))
add_column "test_models", "category", :string
add_index :test_models, :category, name: long_index_name
change_column "test_models", "category", :string, null: false, default: 'article'
assert_equal [long_index_name], connection.indexes('test_models').map(&:name)
end
def test_change_column_default
add_column "test_models", "first_name", :string
connection.change_column_default "test_models", "first_name", "Tester"
assert_equal "Tester", TestModel.new.first_name
end
def test_change_column_default_to_null
add_column "test_models", "first_name", :string
connection.change_column_default "test_models", "first_name", nil
assert_nil TestModel.new.first_name
end
def test_remove_column_no_second_parameter_raises_exception
assert_raise(ArgumentError) { connection.remove_column("funny") }
end
def test_removing_and_renaming_column_preserves_custom_primary_key
connection.create_table "my_table", primary_key: "my_table_id", force: true do |t|
t.integer "col_one"
t.string "col_two", limit: 128, null: false
end
remove_column("my_table", "col_two")
rename_column("my_table", "col_one", "col_three")
assert_equal 'my_table_id', connection.primary_key('my_table')
ensure
connection.drop_table(:my_table) rescue nil
end
def test_column_with_index
connection.create_table "my_table", force: true do |t|
t.string :item_number, index: true
end
assert connection.index_exists?("my_table", :item_number, name: :index_my_table_on_item_number)
ensure
connection.drop_table(:my_table) rescue nil
end
end
end
end