aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/migration/command_recorder.rb
diff options
context:
space:
mode:
authorMarc-Andre Lafortune <github@marc-andre.ca>2012-08-06 20:44:05 -0400
committerMarc-Andre Lafortune <github@marc-andre.ca>2012-12-21 13:54:51 -0500
commitd327c1805a58641a15d76e5e7de2f3fa1c0b9d03 (patch)
tree0b486628402e22288afa775ee92b15cf6c68fdfa /activerecord/lib/active_record/migration/command_recorder.rb
parent740dbf8d42f6bef86845086690ac522cf91ceece (diff)
downloadrails-d327c1805a58641a15d76e5e7de2f3fa1c0b9d03.tar.gz
rails-d327c1805a58641a15d76e5e7de2f3fa1c0b9d03.tar.bz2
rails-d327c1805a58641a15d76e5e7de2f3fa1c0b9d03.zip
Allow reverting of migration commands with Migration#revert [#8267]
Diffstat (limited to 'activerecord/lib/active_record/migration/command_recorder.rb')
-rw-r--r--activerecord/lib/active_record/migration/command_recorder.rb53
1 files changed, 36 insertions, 17 deletions
diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb
index 55c384ae41..a79428b69a 100644
--- a/activerecord/lib/active_record/migration/command_recorder.rb
+++ b/activerecord/lib/active_record/migration/command_recorder.rb
@@ -16,35 +16,54 @@ module ActiveRecord
class CommandRecorder
include JoinTable
- attr_accessor :commands, :delegate
+ attr_accessor :commands, :delegate, :reverting
def initialize(delegate = nil)
@commands = []
@delegate = delegate
+ @reverting = false
+ end
+
+ # 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])
+ def revert
+ @reverting = !@reverting
+ previous = @commands
+ @commands = []
+ yield
+ ensure
+ @commands = previous.concat(@commands.reverse)
+ @reverting = !@reverting
end
# record +command+. +command+ should be a method name and arguments.
# For example:
#
# recorder.record(:method_name, [:arg1, :arg2])
- def record(*command)
- @commands << command
+ def record(*command, &block)
+ if @reverting
+ @commands << inverse_of(*command, &block)
+ else
+ @commands << (command << block)
+ end
end
- # Returns a list that represents commands that are the inverse of the
- # commands stored in +commands+. For example:
+ # Returns the inverse of the given command. For example:
#
- # recorder.record(:rename_table, [:old, :new])
- # recorder.inverse # => [:rename_table, [:new, :old]]
+ # recorder.inverse_of(:rename_table, [:old, :new])
+ # # => [:rename_table, [:new, :old]]
#
# This method will raise an +IrreversibleMigration+ exception if it cannot
- # invert the +commands+.
- def inverse
- @commands.reverse.map { |name, args|
- method = :"invert_#{name}"
- raise IrreversibleMigration unless respond_to?(method, true)
- send(method, args)
- }
+ # invert the +command+.
+ def inverse_of(command, args, &block)
+ method = :"invert_#{command}"
+ raise IrreversibleMigration unless respond_to?(method, true)
+ send(method, args, &block)
end
def respond_to?(*args) # :nodoc:
@@ -56,9 +75,9 @@ module ActiveRecord
:change_column, :change_column_default, :add_reference, :remove_reference,
].each do |method|
class_eval <<-EOV, __FILE__, __LINE__ + 1
- def #{method}(*args) # def create_table(*args)
- record(:"#{method}", args) # record(:create_table, args)
- end # end
+ def #{method}(*args, &block) # def create_table(*args, &block)
+ record(:"#{method}", args, &block) # record(:create_table, args, &block)
+ end # end
EOV
end
alias :add_belongs_to :add_reference