失敗したRails移行をどのようにロールバックしますか?rake db:rollback
は失敗した移行を取り消しますが、いいえ、前の移行をロールバックします(失敗した移行から1を引いたもの)。そして、rake db:migrate:down VERSION=myfailedmigration
も機能しません。これに何度か遭遇しましたが、とてもイライラします。以下は、問題を再現するために行った簡単なテストです。
class SimpleTest < ActiveRecord::Migration
def self.up
add_column :assets, :test, :integer
# the following syntax error will cause the migration to fail
add_column :asset, :test2, :integer
end
def self.down
remove_column :assets, :test
remove_column :assets, :test2
end
end
結果:
== SimpleTest:移行中====================================== ============= -add_column(:assets、:test、:integer) -> 0.0932s -add_column(: asset、:error) rake aborted! エラーが発生し、その後の移行はすべてキャンセルされました: 間違った数の引数(2で3)
oK、ロールバックしてみましょう:
$ rake db:rollback == AddLevelsToRoles:reverting ============================= ================= -remove_column(:roles、:level) -> 0.0778s == AddLevelsToRoles:復帰(0.0779s)=====================================
え?これはSimpleTestの前の最後の移行であり、移行の失敗ではありません。 (ああ、移行の出力にバージョン番号が含まれていればいいですね。)
失敗した移行SimpleTestのダウンを実行してみましょう。
$ rake db:migrate:down VERSION = 20090326173033 $
何も起こらず、出力もありません。しかし、とにかく移行を実行したのでしょうか?そのため、SimpleTest移行の構文エラーを修正して、もう一度実行してみてください。
$ rake db:migrate:up VERSION = 20090326173033 == SimpleTest:migrating ======================== ============================ -add_column(:assets、:test、:integer) rake aborted! Mysql :: Error:重複したカラム名 'test':ALTER TABLE `assets` ADD` test` int(11)
いや。明らかに、migrate:downは機能しませんでした。失敗ではなく、実行されていないだけです。
手動でデータベースにアクセスして削除してから、テストを実行する以外に、その重複したテーブルを削除する方法はありません。それよりも良い方法がなければなりません。
残念ながら、MySQLの失敗した移行を手動でクリーンアップする必要があります。 MySQLは、トランザクションデータベース定義の変更をサポートしていません。
Rails 2.2には、PostgreSQLのトランザクション移行が含まれています。 Rails 2.3にはSQLiteのトランザクション移行が含まれています。
これは今のところあなたの問題の解決には本当に役立ちませんが、将来のプロジェクトでデータベースを選択できる場合は、トランザクションDDLをサポートするデータベースを使用することをお勧めします。
更新-これは2017年も引き続き有効、Rails 4.2.7およびMySQL 5.7、別の回答でAlejandro Babioによって報告されました。
指定したバージョンに移動するには、次を使用します。
rake db:migrate VERSION=(the version you want to go to)
ただし、移行が途中で失敗した場合は、最初にクリーンアップする必要があります。 1つの方法は次のとおりです。
down
メソッドを編集して、機能したup
の一部を元に戻すdown
への変更の取り消しを含む)さて、皆さん、これが実際のやり方です。上記の答えが何を言っているのか分かりません。
あなたが今それを持っていることを確認したいなら、あなたは再び移行してバックアップすることができます。
可能であればPostgreSQLを使用する必要があることに同意します。ただし、MySQLにこだわっている場合は、最初にテストデータベースで移行を試みることで、これらの問題のほとんどを回避できます。
rake db:migrate Rails_ENV=test
前の状態に戻って、もう一度試すことができます
rake db:schema:load Rails_ENV=test
2015年にRails 4.2.1およびMySQL 5.7で、移行の失敗は、2009年のようにRails提供する標準のrakeアクションでは修正できません。 。
MySqlは、DDLステートメントのロールバックをサポートしていません( MySQL 5.7 Manual )。そしてRailsはそれで何もできません。
また、Railsがどのようにジョブを実行しているかを確認できます。移行は トランザクションにラップされています 接続アダプターが:supports_ddl_transactions?
。 Rails source(v 4.2.1)でこのアクションを検索した後、トランザクションをサポートしているのは Sqlite および PostgreSql のみであり、 デフォルト ではサポートされていません。
Editしたがって、元の質問に対する現在の答え:失敗したMySQL移行は手動で修正する必要があります。
これを行う簡単な方法は、すべてのアクションをトランザクションでラップすることです。
class WhateverMigration < ActiveRecord::Migration
def self.up
ActiveRecord::Base.transaction do
...
end
end
def self.down
ActiveRecord::Base.transaction do
...
end
end
end
Luke Franclが述べたように、「MySql [のMyISAMテーブルはトランザクションをサポートしていません」-これが、MySQL全般または少なくともMyISAMを避けることを検討する理由です。
MySQLのInnoDBを使用している場合、上記は問題なく機能します。アップまたはダウンのいずれかのエラーはバックアウトします。
BE AWARE一部のタイプのアクションは、トランザクションを介して元に戻すことはできません。通常、テーブルの変更(テーブルの削除、列の削除または追加など)はロールバックできません。
コンソールからダウンマイグレーションのみを実行します。
http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (クリックして彼のペーストリーへ)
タイプミスがありました(「add_column」内):
def self.up
add_column :medias, :title, :text add_colunm :medias, :enctype, :text
終わり
def self.down
remove_column :medias, :title remove_column :medias, :enctype
終わり
そして、あなたの問題(部分的に失敗した移行を元に戻すことはできません)。いくつかのグーグルに失敗した後、私はこれを実行しました:
def self.up
remove_column :medias, :title add_column :medias, :title, :text add_column :medias, :enctype, :text
終わり
def self.down
remove_column :medias, :title remove_column :medias, :enctype
終わり
ご覧のとおり、修正ラインを手動で追加し、チェックインする前に再度削除しました。
上記のAlejandro Babioの答えは、現在の最良の答えを提供します。
追加したい追加の詳細:
myfailedmigration
の移行が失敗した場合、適用済みとは見なされません。これは、rake db:migrate:status
を実行することで確認できます。次のような出力が表示されます。
$ rake db:migrate:status
database: sample_app_dev
Status Migration ID Migration Name
--------------------------------------------------
up 20130206203115 Create users
...
...
down 20150501173156 Test migration
失敗した移行で実行されるadd_column :assets, :test, :integer
の残留効果は、alter table assets drop column test;
クエリを使用してデータベースレベルで元に戻す必要があります。