質問

失敗した 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: migrating =====================================================
-- add_column(:assets, :test, :integer)
   -> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:

wrong number of arguments (2 for 3)

OK、ロールバックしましょう:

$ rake db:rollback
==  AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
   -> 0.0778s
==  AddLevelsToRoles: reverted (0.0779s) ======================================

はぁ?これは、失敗した移行ではなく、SimpleTest の前の最後の移行でした。(そして、移行の出力にバージョン番号が含まれていれば良いのですが。)

そこで、失敗した移行の SimpleTest に対して down を実行してみましょう。

$ rake db:migrate:down VERSION=20090326173033
$

何も起こらず、出力もありません。しかし、とにかく移行を実行したのでしょうか?そこで、SimpleTest 移行の構文エラーを修正し、再度実行してみます。

$ rake db:migrate:up VERSION=20090326173033
==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)

いいえ。明らかに、mitigate:down は機能しませんでした。失敗しているのではなく、実行していないだけなのです。

手動でデータベースにアクセスして削除し、テストを実行する以外に重複テーブルを削除する方法はありません。それよりも良い方法があるはずです。

役に立ちましたか?

解決

残念なことに、手動でMySQLの失敗の移行をクリーンアップする必要があります。 MySQLはトランザクションデータベースの定義の変更をサポートしていません。

レール2.2は、PostgreSQLのトランザクションの移行を含みます。レール2.3はSQLiteのためにトランザクションの移行が含まれます。

これは本当に今、あなたの問題のためのお手伝いをしませんが、あなたは将来のプロジェクトのデータベースの選択肢を持っている場合、それははるかに快適な移行を作るので、私はトランザクションのDDLをサポートするものを使用することをお勧めします。

のアップデート - これは、ここで別の答えにアレハンドロBabioによって報告Railsの4.2.7とMySQL 5.7、に、2017年にはまだ本当です。

他のヒント

指定したバージョンに移動するには、次のコマンドを使用します。

rake db:migrate VERSION=(the version you want to go to)

ただし、移行が途中で失敗した場合は、最初に移行をクリーンアップする必要があります。1 つの方法は次のとおりです。

  • 編集する down の一部を元に戻すだけの移行方法 up それはうまくいきました
  • 以前の状態 (開始した場所) に戻る
  • 移行を修正します (変更を元に戻すなど) down)
  • もう一度やり直してください

OK、皆さん、これが実際のやり方です。上記の回答が何を言っているのかわかりません。

  1. 上への移行のどの部分が機能したかを確認します。それらをコメントアウトしてください。
  2. また、壊れた移行の部分をコメントアウトするか削除します。
  3. 移行を再度実行します。これで、すでに完了した部分をスキップして、移行の壊れていない部分が完了します。
  4. 手順 1 でコメントアウトした移行の部分のコメントを解除します。

すぐに取得したことを確認したい場合は、下に移行して再度バックアップすることができます。

私は、可能な場合、あなたは、PostgreSQLを使用する必要があることに同意するものとします。あなたがMySQLので立ち往生しているときしかし、あなたが最初のテストデータベースに移行を試みることによって、これらの問題のほとんどを回避することができます:

rake db:migrate RAILS_ENV=test

あなたが以前の状態に戻して再び試すことができます。

rake db:schema:load RAILS_ENV=test

Rails 4.2.1 と MySQL 5.7 を使用する 2015 年では、2009 年と同様に、失敗した移行は Rails が提供する標準の rake アクションでは修正できません。

MySql は DDL ステートメントのロールバックをサポートしていません ( MySQL 5.7 マニュアル)。そして、Rails はそれに対して何もできません。

また、Rails がどのようにジョブを実行しているかを確認することもできます。移行というのは、 トランザクションにラップされる 接続アダプターの応答方法に応じて :supports_ddl_transactions?. 。Rails ソース (v 4.2.1) でこのアクションを検索したところ、次のことがわかりました。 スクライト3 そして PostgreSql トランザクションをサポートし、 デフォルト それはサポートされていません。

編集したがって、元の質問に対する現在の答えは次のようになります。失敗した MySQL 移行は手動で修正する必要があります。

これを行う簡単な方法は、トランザクションにあなたの行動のすべてをラップすることです。

class WhateverMigration < ActiveRecord::Migration

 def self.up
    ActiveRecord::Base.transaction do
...
    end
  end

  def self.down
    ActiveRecord::Base.transaction do
...
    end
  end

end

ルークFranclは、「MySQLのサポート取引[ 'sのMyISAMテーブルにはない]」、述べたように - 。あなたは一般的または具体的には、少なくともMyISAMテーブルにMySQLを回避検討するかもしれない理由です。

あなたはMySQLのInnoDBのを使用している場合は、上記だけで正常に動作します。上または下のいずれかにエラーがあると、バックアウトされます。

に注意して行動のいくつかのタイプは、トランザクションを経由して元に戻すことはできません。一般的に、(など、列を削除または追加して、テーブルをドロップ)テーブルの変更がロールバックすることができない。

コンソールからちょうどダウンの移行を実行します:

のhttp://gilesbowkett.blogspot .COM / 2007/07 /どのように使用-移行-から-console.html に(彼pastieにクリックスルー)

私はタイプミスがあった( "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
     

終了

あなたが見ることができるように

私はそれを確認する前に、ちょうど手で補正ラインを追加し、再度それを取り除いています。

上記のアレハンドロBabioの答えは最高の現在の答えを提供します。

私は追加したい1つの追加の詳細ます:

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;クエリを使用してデータベースレベルで反転されなければならない。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top