class ActiveRecord::Migration::CommandRecorder
-
rename_table
* rename_index
* rename_column
* remove_timestamps
* create_join_table
* create_table
* add_timestamps
* add_index
* add_column
knows how to invert the following commands:
a migration and knows how to reverse those commands. The CommandRecorderActiveRecord::Migration::CommandRecorder
records commands done during
def change_table(table_name, options = {}) # :nodoc:
def change_table(table_name, options = {}) # :nodoc: yield delegate.update_table_definition(table_name, self) end
def initialize(delegate = nil)
def initialize(delegate = nil) @commands = [] @delegate = delegate @reverting = false end
def inverse_of(command, args, &block)
This method will raise an +IrreversibleMigration+ exception if it cannot
# => [:rename_table, [:new, :old]]
recorder.inverse_of(:rename_table, [:old, :new])
Returns the inverse of the given command. For example:
def inverse_of(command, args, &block) method = :"invert_#{command}" raise IrreversibleMigration unless respond_to?(method, true) send(method, args, &block) end
def invert_add_foreign_key(args)
def invert_add_foreign_key(args) from_table, to_table, add_options = args add_options ||= {} if add_options[:name] options = { name: add_options[:name] } elsif add_options[:column] options = { column: add_options[:column] } else options = to_table end [:remove_foreign_key, [from_table, options]] end
def invert_add_index(args)
def invert_add_index(args) table, columns, options = *args options ||= {} index_name = options[:name] options_hash = index_name ? { name: index_name } : { column: columns } [:remove_index, [table, options_hash]] end
def invert_change_column_null(args)
def invert_change_column_null(args) args[2] = !args[2] [:change_column_null, args] end
def invert_drop_table(args, &block)
def invert_drop_table(args, &block) if args.size == 1 && block == nil raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)." end super end
def invert_remove_column(args)
def invert_remove_column(args) raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2 super end
def invert_remove_index(args)
def invert_remove_index(args) table, options = *args unless options && options.is_a?(Hash) && options[:column] raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option." end options = options.dup [:add_index, [table, options.delete(:column), options]] end
def invert_rename_column(args)
def invert_rename_column(args) [:rename_column, [args.first] + args.last(2).reverse] end
def invert_rename_index(args)
def invert_rename_index(args) [:rename_index, [args.first] + args.last(2).reverse] end
def invert_rename_table(args)
def invert_rename_table(args) [:rename_table, args.reverse] end
def method_missing(method, *args, &block)
def method_missing(method, *args, &block) if @delegate.respond_to?(method) @delegate.send(method, *args, &block) else super end end
def record(*command, &block)
For example:
record +command+. +command+ should be a method name and arguments.
def record(*command, &block) if @reverting @commands << inverse_of(*command, &block) else @commands << (command << block) end end
def respond_to?(*args) # :nodoc:
def respond_to?(*args) # :nodoc: super || delegate.respond_to?(*args) end
def revert
recorder.revert{ recorder.record(:rename_table, [:old, :new]) }
For example:
and in reverse order.
All commands recorded will end up being recorded reverted
While executing the given block, the recorded will be in reverting mode.
def revert @reverting = !@reverting previous = @commands @commands = [] yield ensure @commands = previous.concat(@commands.reverse) @reverting = !@reverting end