Skip to content
Browse files

Support transactions in Migrator.run

  • Loading branch information...
1 parent 130d3a0 commit 2976558bc3a02019b605a1d70fda76ba5e9b5df2 @mirasrael mirasrael committed Feb 25, 2013
View
4 activerecord/CHANGELOG.md
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##
+* Run migrate:down & migrate:up in transaction if database supports
+
+ *Alexander Bondarev*
+
* Added Statement Cache to allow the caching of a single statement. The cache works by
duping the relation returned from yielding a statement, which allows skipping the AST
building phase for following executes. The cache returns results in array format.
View
17 activerecord/lib/active_record/migration.rb
@@ -867,11 +867,18 @@ def current_migration
alias :current :current_migration
def run
- target = migrations.detect { |m| m.version == @target_version }
- raise UnknownMigrationVersionError.new(@target_version) if target.nil?
- unless (up? && migrated.include?(target.version.to_i)) || (down? && !migrated.include?(target.version.to_i))
- target.migrate(@direction)
- record_version_state_after_migrating(target.version)
+ migration = migrations.detect { |m| m.version == @target_version }
+ raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
+ unless (up? && migrated.include?(migration.version.to_i)) || (down? && !migrated.include?(migration.version.to_i))
+ begin
+ ddl_transaction(migration) do
+ migration.migrate(@direction)
+ record_version_state_after_migrating(migration.version)
+ end
+ rescue => e
+ canceled_msg = use_transaction?(migration) ? ", the migration canceled" : ""
+ raise StandardError, "An error has occurred#{canceled_msg}:\n\n#{e}", e.backtrace
+ end
end
end
View
26 activerecord/test/cases/migration_test.rb
@@ -258,6 +258,32 @@ def migrate(x)
"On error, the Migrator should revert schema changes but it did not."
end
+ def test_migrator_one_up_with_exception_and_rollback_using_run
+ unless ActiveRecord::Base.connection.supports_ddl_transactions?
+ skip "not supported on #{ActiveRecord::Base.connection.class}"
+ end
+
+ assert_not Person.column_methods_hash.include?(:last_name)
+
+ migration = Class.new(ActiveRecord::Migration) {
+ def version; 100 end
+ def migrate(x)
+ add_column "people", "last_name", :string
+ raise 'Something broke'
+ end
+ }.new
+
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
+
+ e = assert_raise(StandardError) { migrator.run }
+
+ assert_equal "An error has occurred, the migration canceled:\n\nSomething broke", e.message
+
+ Person.reset_column_information
+ assert_not Person.column_methods_hash.include?(:last_name),
+ "On error, the Migrator should revert schema changes but it did not."
+ end
+
def test_migration_without_transaction
unless ActiveRecord::Base.connection.supports_ddl_transactions?
skip "not supported on #{ActiveRecord::Base.connection.class}"

0 comments on commit 2976558

Please sign in to comment.
Something went wrong with that request. Please try again.