mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add reversible syntax for change_column_default
Passing `:from` and `:to` to `change_column_default` makes this command reversible as user has defined its previous state. So, instead of having the migration command as: change_column_default(:posts, :state, "draft") They can write it as: change_column_default(:posts, :state, from: nil, to: "draft")
This commit is contained in:
parent
0bee4100f1
commit
a4128725f5
9 changed files with 64 additions and 7 deletions
|
@ -1,3 +1,15 @@
|
|||
* Add alternate syntax to make `change_column_default` reversible.
|
||||
|
||||
User can pass in `:from` and `:to` to make `change_column_default` command
|
||||
become reversible.
|
||||
|
||||
Example:
|
||||
|
||||
change_column_default :posts, :status, from: nil, to: "draft"
|
||||
change_column_default :users, authorized, from: true, to: false
|
||||
|
||||
*Prem Sichanugrist*
|
||||
|
||||
* Prevent error when using `force_reload: true` on an unassigned polymorphic
|
||||
belongs_to association.
|
||||
|
||||
|
|
|
@ -592,10 +592,11 @@ module ActiveRecord
|
|||
#
|
||||
# t.change_default(:qualification, 'new')
|
||||
# t.change_default(:authorized, 1)
|
||||
# t.change_default(:status, from: nil, to: "draft")
|
||||
#
|
||||
# See SchemaStatements#change_column_default
|
||||
def change_default(column_name, default)
|
||||
@base.change_column_default(name, column_name, default)
|
||||
def change_default(column_name, default_or_changes)
|
||||
@base.change_column_default(name, column_name, default_or_changes)
|
||||
end
|
||||
|
||||
# Removes the column(s) from the table definition.
|
||||
|
|
|
@ -460,7 +460,12 @@ module ActiveRecord
|
|||
#
|
||||
# change_column_default(:users, :email, nil)
|
||||
#
|
||||
def change_column_default(table_name, column_name, default)
|
||||
# Passing a hash containing +:from+ and +:to+ will make this change
|
||||
# reversible in migration:
|
||||
#
|
||||
# change_column_default(:posts, :state, from: nil, to: "draft")
|
||||
#
|
||||
def change_column_default(table_name, column_name, default_or_changes)
|
||||
raise NotImplementedError, "change_column_default is not implemented"
|
||||
end
|
||||
|
||||
|
@ -1068,6 +1073,14 @@ module ActiveRecord
|
|||
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
|
||||
end
|
||||
end
|
||||
|
||||
def extract_new_default_value(default_or_changes)
|
||||
if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
|
||||
default_or_changes[:to]
|
||||
else
|
||||
default_or_changes
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -629,7 +629,8 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def change_column_default(table_name, column_name, default) #:nodoc:
|
||||
def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
|
||||
default = extract_new_default_value(default_or_changes)
|
||||
column = column_for(table_name, column_name)
|
||||
change_column table_name, column_name, column.sql_type, :default => default
|
||||
end
|
||||
|
|
|
@ -410,11 +410,12 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# Changes the default value of a table column.
|
||||
def change_column_default(table_name, column_name, default) # :nodoc:
|
||||
def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
|
||||
clear_cache!
|
||||
column = column_for(table_name, column_name)
|
||||
return unless column
|
||||
|
||||
default = extract_new_default_value(default_or_changes)
|
||||
alter_column_query = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} %s"
|
||||
if default.nil?
|
||||
# <tt>DEFAULT NULL</tt> results in the same behavior as <tt>DROP DEFAULT</tt>. However, PostgreSQL will
|
||||
|
|
|
@ -422,7 +422,9 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def change_column_default(table_name, column_name, default) #:nodoc:
|
||||
def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
|
||||
default = extract_new_default_value(default_or_changes)
|
||||
|
||||
alter_table(table_name) do |definition|
|
||||
definition[column_name].default = default
|
||||
end
|
||||
|
|
|
@ -72,7 +72,7 @@ module ActiveRecord
|
|||
|
||||
[:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
||||
:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
|
||||
:change_column_default, :add_reference, :remove_reference, :transaction,
|
||||
:add_reference, :remove_reference, :transaction,
|
||||
:drop_join_table, :drop_table, :execute_block, :enable_extension,
|
||||
:change_column, :execute, :remove_columns, :change_column_null,
|
||||
:add_foreign_key, :remove_foreign_key
|
||||
|
@ -166,6 +166,16 @@ module ActiveRecord
|
|||
alias :invert_add_belongs_to :invert_add_reference
|
||||
alias :invert_remove_belongs_to :invert_remove_reference
|
||||
|
||||
def invert_change_column_default(args)
|
||||
table, column, options = *args
|
||||
|
||||
unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
|
||||
raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
|
||||
end
|
||||
|
||||
[:change_column_default, [table, column, from: options[:to], to: options[:from]]]
|
||||
end
|
||||
|
||||
def invert_change_column_null(args)
|
||||
args[2] = !args[2]
|
||||
[:change_column_null, args]
|
||||
|
|
|
@ -267,6 +267,13 @@ module ActiveRecord
|
|||
assert_nil TestModel.new.first_name
|
||||
end
|
||||
|
||||
def test_change_column_default_with_from_and_to
|
||||
add_column "test_models", "first_name", :string
|
||||
connection.change_column_default "test_models", "first_name", from: nil, to: "Tester"
|
||||
|
||||
assert_equal "Tester", TestModel.new.first_name
|
||||
end
|
||||
|
||||
def test_remove_column_no_second_parameter_raises_exception
|
||||
assert_raise(ArgumentError) { connection.remove_column("funny") }
|
||||
end
|
||||
|
|
|
@ -169,6 +169,16 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def test_invert_change_column_default_with_from_and_to
|
||||
change = @recorder.inverse_of :change_column_default, [:table, :column, from: "old_value", to: "new_value"]
|
||||
assert_equal [:change_column_default, [:table, :column, from: "new_value", to: "old_value"]], change
|
||||
end
|
||||
|
||||
def test_invert_change_column_default_with_from_and_to_with_boolean
|
||||
change = @recorder.inverse_of :change_column_default, [:table, :column, from: true, to: false]
|
||||
assert_equal [:change_column_default, [:table, :column, from: false, to: true]], change
|
||||
end
|
||||
|
||||
def test_invert_change_column_null
|
||||
add = @recorder.inverse_of :change_column_null, [:table, :column, true]
|
||||
assert_equal [:change_column_null, [:table, :column, false]], add
|
||||
|
|
Loading…
Reference in a new issue