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_index

  • add_reference

  • add_timestamps

  • change_column

  • change_column_default (must supply a :from and :to option)

  • change_column_null

  • change_column_comment (must supply a :from and :to option)

  • change_table_comment (must supply a :from and :to option)

  • create_join_table

  • create_table

  • disable_extension

  • drop_join_table

  • drop_table (must supply a block)

  • enable_extension

  • remove_column (must supply a type)

  • remove_columns (must specify at least one column name or more)

  • remove_foreign_key (must supply a second table)

  • remove_check_constraint

  • remove_index

  • remove_reference

  • remove_timestamps

  • rename_column

  • rename_index

  • rename_table

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 ]

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 51
      def initialize(delegate = nil)
        @commands = []
        @delegate = delegate
        @reverting = false
      end
🔎 See on GitHub

Instance 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 98
      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)
      end
🔎 See on GitHub

record(*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 78
      def record(*command, &block)
        if @reverting
          @commands << inverse_of(*command, &block)
        else
          @commands << (command << block)
        end
      end
🔎 See on GitHub

replay(migration)

📝 Source code
# File activerecord/lib/active_record/migration/command_recorder.rb, line 124
      def replay(migration)
        commands.each do |cmd, args, block|
          migration.send(cmd, *args, &block)
        end
      end
🔎 See on GitHub

revert()

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 64
      def revert
        @reverting = !@reverting
        previous = @commands
        @commands = []
        yield
      ensure
        @commands = previous.concat(@commands.reverse)
        @reverting = !@reverting
      end
🔎 See on GitHub