Migration Command Recorder
ActiveRecord::Migration::CommandRecorder records commands done during a migration and knows how to reverse those commands. The CommandRecorder knows how to invert the following commands:
- 
add_column 
- 
add_foreign_key 
- 
add_check_constraint 
- 
add_exclusion_constraint 
- 
add_unique_constraint 
- 
add_index 
- 
add_reference 
- 
add_timestamps 
- 
change_column_default (must supply a :fromand:tooption)
- 
change_column_null 
- 
change_column_comment (must supply a :fromand:tooption)
- 
change_table_comment (must supply a :fromand:tooption)
- 
create_enum 
- 
create_join_table 
- 
create_virtual_table 
- 
create_table 
- 
disable_extension 
- 
drop_enum (must supply a list of values) 
- 
drop_join_table 
- 
drop_virtual_table (must supply options) 
- 
drop_table (must supply a block) 
- 
enable_extension 
- 
remove_column (must supply a type) 
- 
remove_columns (must supply a :typeoption)
- 
remove_foreign_key (must supply a second table) 
- 
remove_check_constraint 
- 
remove_exclusion_constraint 
- 
remove_unique_constraint 
- 
remove_index 
- 
remove_reference 
- 
remove_timestamps 
- 
rename_column 
- 
rename_enum 
- 
rename_enum_value (must supply a :fromand:tooption)
- 
rename_index 
- 
rename_table 
- 
enable_index 
- 
disable_index 
Methods
Constants
| ReversibleAndIrreversibleMethods | = | [ :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, :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension, :change_column, :execute, :remove_columns, :change_column_null, :add_foreign_key, :remove_foreign_key, :change_column_comment, :change_table_comment, :add_check_constraint, :remove_check_constraint, :add_exclusion_constraint, :remove_exclusion_constraint, :add_unique_constraint, :remove_unique_constraint, :create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value, :create_schema, :drop_schema, :create_virtual_table, :drop_virtual_table, :enable_index, :disable_index ] | 
Attributes
| [RW] | commands | |
| [RW] | delegate | |
| [RW] | reverting | 
Class Public methods
new(delegate = nil)
          
          
          
          
          
            📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 70
def initialize(delegate = nil)
  @commands = []
  @delegate = delegate
  @reverting = false
endInstance Public methods
inverse_of(command, args, &block)
          Returns the inverse of the given command. For example:
recorder.inverse_of(:rename_table, [:old, :new])
# => [:rename_table, [:new, :old]]
If the inverse of a command requires several commands, returns array of commands.
recorder.inverse_of(:remove_columns, [:some_table, :foo, :bar, type: :string])
# => [[:add_column, :some_table, :foo, :string], [:add_column, :some_table, :bar, :string]]
This method will raise an IrreversibleMigration exception if it cannot invert the command.
📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 117
def inverse_of(command, args, &block)
  method = :"invert_#{command}"
  raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
    This migration uses #{command}, which is not automatically reversible.
    To make the migration reversible you can either:
    1. Define #up and #down methods in place of the #change method.
    2. Use the #reversible method to define reversible behavior.
  MSG
  send(method, args, &block)
endrecord(*command, &block)
          Record command. command should be a method name and arguments. For example:
recorder.record(:method_name, [:arg1, :arg2])
📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 97
def record(*command, &block)
  if @reverting
    @commands << inverse_of(*command, &block)
  else
    @commands << (command << block)
  end
endreplay(migration)
          
          
          
          
          
            📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 151
def replay(migration)
  commands.each do |cmd, args, block|
    migration.send(cmd, *args, &block)
  end
endrevert()
          While executing the given block, the recorded will be in reverting mode. All commands recorded will end up being recorded reverted and in reverse order. For example:
recorder.revert{ recorder.record(:rename_table, [:old, :new]) }
# same effect as recorder.record(:rename_table, [:new, :old])
📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 83
def revert
  @reverting = !@reverting
  previous = @commands
  @commands = []
  yield
ensure
  @commands = previous.concat(@commands.reverse)
  @reverting = !@reverting
end