Class: ActiveRecord::Migration::CommandRecorder
| Relationships & Source Files | |
| Namespace Children | |
|
Modules:
| |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
StraightReversions
|
|
| Inherits: | Object |
| Defined in: | activerecord/lib/active_record/migration/command_recorder.rb |
Overview
Migration Command Recorder
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
Constant Summary
-
ReversibleAndIrreversibleMethods =
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 50[ :create_table, :create_join_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :, :, :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 ].freeze
Class Method Summary
- .new(delegate = nil) ⇒ CommandRecorder constructor
Instance Attribute Summary
- #commands rw
- #delegate rw
- #reverting rw
Instance Method Summary
- #add_belongs_to
-
#invert_add_belongs_to(args, kwargs)
Alias for #invert_add_reference.
- #invert_add_check_constraint(args, kwargs)
- #invert_add_column(args, kwargs)
- #invert_add_foreign_key(args, kwargs)
- #invert_add_index(args, kwargs)
- #invert_add_reference(args, kwargs) (also: #invert_add_belongs_to)
- #invert_add_unique_constraint(args, kwargs)
- #invert_change_column_comment(args, kwargs)
- #invert_change_column_default(args, kwargs)
- #invert_change_column_null(args, kwargs)
- #invert_change_table_comment(args, kwargs)
- #invert_create_table(args, kwargs, &block)
- #invert_disable_index(args, kwargs)
- #invert_drop_enum(args, kwargs)
- #invert_drop_table(args, kwargs, &block)
- #invert_drop_virtual_table(args, kwargs)
- #invert_enable_index(args, kwargs)
-
#invert_remove_belongs_to(args, kwargs)
Alias for #invert_remove_reference.
- #invert_remove_check_constraint(args, kwargs)
- #invert_remove_column(args, kwargs)
- #invert_remove_columns(args, kwargs)
- #invert_remove_exclusion_constraint(args, kwargs)
- #invert_remove_foreign_key(args, kwargs)
- #invert_remove_index(args, kwargs)
- #invert_remove_reference(args, kwargs) (also: #invert_remove_belongs_to)
- #invert_remove_unique_constraint(args, kwargs)
- #invert_rename_column(args, kwargs)
- #invert_rename_enum(args, kwargs)
- #invert_rename_enum_value(args, kwargs)
- #invert_rename_index(args, kwargs)
- #invert_rename_table(args, kwargs)
- #invert_transaction(args, kwargs, &block)
-
#method_missing(method)
Forwards any missing method call to the \target.
- #remove_belongs_to
- #replay(migration)
- #respond_to_missing?(method, _) ⇒ Boolean
-
#revert
While executing the given block, the recorded will be in reverting mode.
- #inverse_of(command, args, kwargs, &block) private
- #record(command, args, kwargs, &block) private
- #change_table(table_name, **options) Internal use only
Constructor Details
.new(delegate = nil) ⇒ CommandRecorder
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method)
Forwards any missing method call to the \target.
Instance Attribute Details
#commands (rw)
[ GitHub ]#delegate (rw)
[ GitHub ]#reverting (rw)
[ GitHub ]Instance Method Details
#add_belongs_to
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 99
alias :add_belongs_to :add_reference
#change_table(table_name, **options)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 102
def change_table(table_name, **) # :nodoc: if delegate.supports_bulk_alter? && [:bulk] recorder = self.class.new(self.delegate) recorder.reverting = @reverting yield recorder.delegate.update_table_definition(table_name, recorder) commands = recorder.commands @commands << [:change_table, [table_name], {}, -> t { bulk_change_table(t.name, commands.reverse) }] else yield delegate.update_table_definition(table_name, self) end end
#inverse_of(command, args, kwargs, &block) (private)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 129
def inverse_of(command, args, kwargs, &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, kwargs, &block) end
#invert_add_belongs_to(args, kwargs)
Alias for #invert_add_reference.
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 266
alias :invert_add_belongs_to :invert_add_reference
#invert_add_check_constraint(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 325
def invert_add_check_constraint(args, kwargs) kwargs.delete(:validate) kwargs[:if_exists] = kwargs.delete(:if_not_exists) if kwargs.key?(:if_not_exists) super end
#invert_add_column(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 282
def invert_add_column(args, kwargs) kwargs[:if_exists] = kwargs.delete(:if_not_exists) if kwargs.key?(:if_not_exists) super end
#invert_add_foreign_key(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 292
def invert_add_foreign_key(args, kwargs) kwargs.delete(:validate) kwargs[:if_exists] = kwargs.delete(:if_not_exists) if kwargs.key?(:if_not_exists) super end
#invert_add_index(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 287
def invert_add_index(args, kwargs) kwargs[:if_exists] = kwargs.delete(:if_not_exists) if kwargs.key?(:if_not_exists) super end
#invert_add_reference(args, kwargs) Also known as: #invert_add_belongs_to
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 256
def invert_add_reference(args, kwargs) kwargs[:if_exists] = kwargs.delete(:if_not_exists) if kwargs.key?(:if_not_exists) super end
#invert_add_unique_constraint(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 343
def invert_add_unique_constraint(args, kwargs) raise ActiveRecord::IrreversibleMigration, "add_unique_constraint is not reversible if given a using_index." if kwargs[:using_index] super end
#invert_change_column_comment(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 309
def invert_change_column_comment(args, kwargs) unless kwargs.has_key?(:from) && kwargs.has_key?(:to) raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option." end [:change_column_comment, args, { from: kwargs[:to], to: kwargs[:from] }] end
#invert_change_column_default(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 269
def invert_change_column_default(args, kwargs) unless kwargs.has_key?(:from) && kwargs.has_key?(:to) raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option." end [:change_column_default, args, { from: kwargs[:to], to: kwargs[:from] }] end
#invert_change_column_null(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 277
def invert_change_column_null(args, kwargs) table_name, column_name, null, default = args [:change_column_null, [table_name, column_name, !null, default], kwargs] end
#invert_change_table_comment(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 317
def invert_change_table_comment(args, kwargs) unless kwargs.has_key?(:from) && kwargs.has_key?(:to) raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option." end [:change_table_comment, args, { from: kwargs[:to], to: kwargs[:from] }] end
#invert_create_table(args, kwargs, &block)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 192
def invert_create_table(args, kwargs, &block) kwargs.delete(:if_not_exists) super end
#invert_disable_index(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 176
def invert_disable_index(args, kwargs) table_name, index_name = args [:enable_index, [table_name, index_name], kwargs] end
#invert_drop_enum(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 354
def invert_drop_enum(args, kwargs) _enum, values = args raise ActiveRecord::IrreversibleMigration, "drop_enum is only reversible if given a list of enum values." unless values super end
#invert_drop_table(args, kwargs, &block)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 197
def invert_drop_table(args, kwargs, &block) kwargs.delete(:if_exists) if args.size > 1 raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name." end if args.size == 1 && kwargs.empty? && 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
#invert_drop_virtual_table(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 374
def invert_drop_virtual_table(args, kwargs) _table_name, _module_name, values = args raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values super end
#invert_enable_index(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 171
def invert_enable_index(args, kwargs) table_name, index_name = args [:disable_index, [table_name, index_name], kwargs] end
#invert_remove_belongs_to(args, kwargs)
Alias for #invert_remove_reference.
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 267
alias :invert_remove_belongs_to :invert_remove_reference
#invert_remove_check_constraint(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 331
def invert_remove_check_constraint(args, kwargs) raise ActiveRecord::IrreversibleMigration, "remove_check_constraint is only reversible if given an expression." if args.size < 2 kwargs[:if_not_exists] = kwargs.delete(:if_exists) if kwargs.key?(:if_exists) super end
#invert_remove_column(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 216
def invert_remove_column(args, kwargs) if args.size < 3 raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." end kwargs[:if_not_exists] = kwargs.delete(:if_exists) if kwargs.key?(:if_exists) super end
#invert_remove_columns(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 224
def invert_remove_columns(args, kwargs) unless kwargs.key?(:type) raise ActiveRecord::IrreversibleMigration, "remove_columns is only reversible if given a type." end [:add_columns, args, kwargs] end
#invert_remove_exclusion_constraint(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 338
def invert_remove_exclusion_constraint(args, kwargs) raise ActiveRecord::IrreversibleMigration, "remove_exclusion_constraint is only reversible if given an expression." if args.size < 2 super end
#invert_remove_foreign_key(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 298
def invert_remove_foreign_key(args, kwargs) from_table, to_table = args to_table ||= kwargs.delete(:to_table) kwargs[:if_not_exists] = kwargs.delete(:if_exists) if kwargs.key?(:if_exists) raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? [:add_foreign_key, [from_table, to_table], kwargs] end
#invert_remove_index(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 242
def invert_remove_index(args, kwargs) table, columns = args columns ||= kwargs.delete(:column) unless columns raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option." end kwargs[:if_not_exists] = kwargs.delete(:if_exists) if kwargs.key?(:if_exists) [:add_index, [table, columns], kwargs] end
#invert_remove_reference(args, kwargs) Also known as: #invert_remove_belongs_to
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 261
def invert_remove_reference(args, kwargs) kwargs[:if_not_exists] = kwargs.delete(:if_exists) if kwargs.key?(:if_exists) super end
#invert_remove_unique_constraint(args, kwargs)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 348
def invert_remove_unique_constraint(args, kwargs) _table, columns = args raise ActiveRecord::IrreversibleMigration, "remove_unique_constraint is only reversible if given a column_name." if columns.blank? super end
#invert_rename_column(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 237
def invert_rename_column(args, kwargs) table_name, old_name, new_name = args [:rename_column, [table_name, new_name, old_name], kwargs] end
#invert_rename_enum(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 360
def invert_rename_enum(args, kwargs) old_name, new_name = args new_name ||= kwargs.delete(:to) [:rename_enum, [new_name, old_name], kwargs] end
#invert_rename_enum_value(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 366
def invert_rename_enum_value(args, kwargs) unless kwargs.has_key?(:from) && kwargs.has_key?(:to) raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option." end [:rename_enum_value, args, { from: kwargs[:to], to: kwargs[:from] }] end
#invert_rename_index(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 232
def invert_rename_index(args, kwargs) table_name, old_name, new_name = args [:rename_index, [table_name, new_name, old_name], kwargs] end
#invert_rename_table(args, kwargs)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 211
def invert_rename_table(args, kwargs) old_name, new_name = args [:rename_table, [new_name, old_name], kwargs] end
#invert_transaction(args, kwargs, &block)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 181
def invert_transaction(args, kwargs, &block) sub_recorder = CommandRecorder.new(delegate) sub_recorder.revert(&block) invertions_proc = proc { sub_recorder.replay(self) } [:transaction, args, kwargs, invertions_proc] end
#record(command, args, kwargs, &block) (private)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 121
def record(command, args, kwargs, &block) if @reverting @commands << inverse_of(command, args, kwargs, &block) else @commands << [command, args, kwargs, block] end end
#remove_belongs_to
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 100
alias :remove_belongs_to :remove_reference
#replay(migration)
[ GitHub ]# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 114
def replay(migration) commands.each do |cmd, args, kwargs, block| migration.send(cmd, *args, **kwargs, &block) end end
#respond_to_missing?(method, _) ⇒ Boolean
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 380
def respond_to_missing?(method, _) super || delegate.respond_to?(method) end
#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.rename_table(:old, :new) }
# same effect as recorder.rename_table(:new, :old)
# File 'activerecord/lib/active_record/migration/command_recorder.rb', line 82
def revert @reverting = !@reverting previous = @commands @commands = [] yield ensure @commands = previous.concat(@commands.reverse) @reverting = !@reverting end