web-dev-qa-db-ja.com

Rails:不可逆的な移行があるのは悪いことですか?

移行のself.downメソッドでActiveRecord :: IrreversibleMigration例外を発生させることができるのはいつですか?移行の逆を実際に実装するために、いつ努力する必要がありますか?

42
Readonly

製品グレードのシステムを扱っている場合そうです、それは非常に悪いことです。それがあなた自身のペットプロジェクトである場合、何でも許可されます(他に何もない場合、それは学習体験になります:)しかし、ペットプロジェクトであっても、あなたは自分自身がクロスオーバーしたことに気付くでしょう。逆移行は、rakeを介して、または手動で、数日後にその移行を元に戻す必要があるだけです。)

本番シナリオでは、常に書く努力をするそしてテスト可逆的な移行本番環境でそれを経験した場合、あなたを強制するバグを発見する必要があります。以前のリビジョン(重要な修正を保留中-およびそれ以外の場合は使用できない本番システム)にロールバック(コードおよびスキーマ)します。)

逆移行は、ほとんどが些細なもの(移行中に追加された列またはテーブルの削除、および/または列タイプの変更など)からやや複雑なもの(executeedJOINsまたはINSERTsのUPDATE)までさまざまですが、「スイープ」を正当化するほど複雑なものはありません。敷物の下で」。他に何もないとしても、逆移行を実現する方法を考えさせることで、順移行で修正されている問題そのものに新たな洞察を得ることができます。

フォワードマイグレーションによって機能が削除され、データベースからデータが破棄される状況が発生する場合があります。 明らかな理由により、逆方向の移行では破棄されたデータを復活させることはできません。このような場合は、順方向の移行でデータを自動的に保存するか、ロールバックが発生した場合にデータを保持することをお勧めします。失敗(ymlへの保存、特別なテーブルへのコピー/移動など)、そのような自動化された手順のテストに必要な時間は、データを手動で復元するのに必要な時間を超える可能性があるため、そうする必要はありません(必要が生じた場合) 。)ただし、そのような場合でも、単に失敗するのではなく、いつでも逆移行を行うことができます条件付きおよび一時的にユーザーアクションが発生するまで失敗します(つまり、いくつかの存在をテストします)手動で復元する必要のある必要なテーブル。欠落している場合は、「テーブルXYZを何もないところから再作成できないため失敗しました。バックアップからテーブルXYZを手動で復元してから、もう一度実行してください。失敗しません!」)

54
vladr

データを破棄する場合は、最初にデータのバックアップを作成できます。例えば.

def self.up
  # create a backup table before destroying data 
  execute %Q[create table backup_users select * from users]  
  remove_column :users, :timezone
end  

def self.down
  add_column :users, :timezone, :string  
  execute %Q[update users U left join backup_users B on (B.id=U.id) set U.timezone = B.timezone]
  execute %Q[drop table backup_users]  
end
28
Mark Lanett

本番シナリオでは、本番環境でリバーシブル移行を実行した場合に備えて、リバーシブル移行を作成してテストするように常に努力する必要があります。次に、以前のリビジョン(保留中)にロールバック(コードとスキーマ)する必要があるバグを発見します。いくつかの重要な修正-そして他の方法では使用できない本番システム。)

開発とステージングにはリバーシブル移行を使用することは問題ありませんが、十分にテストされたコードを想定すると、本番環境に移行することは非常にまれです。実稼働モードで自動IrreversibleMigrationを移行に組み込みます。本当に変更を元に戻す必要がある場合は、別の「アップ」移行を使用するか、例外を削除することができます。しかし、それは大ざっぱなようです。この悲惨なシナリオを引き起こすバグは、QAプロセスが深刻に台無しになっていることを示しています。

7
jdl

不可逆的な移行が必要だと感じているのは、おそらく、より大きな問題が迫っている兆候です。たぶんいくつかの詳細が役立つでしょうか?

あなたの2番目の質問に関して:私は常に移行の逆を書くために「努力」をします。もちろん、[〜#〜] i [〜#〜]実際には.downを記述しないでください。TextMateは、.upを作成するときに自動的に挿入します。

3
rfunduk

リバーシブルデータ移行 yamlファイルを使用してリバーシブルデータ移行を簡単に作成できます。

class RemoveStateFromProduct < ActiveRecord::Migration
  def self.up
    backup_data = []
    Product.all.each do |product|
      backup_data << {:id => product.id, :state => product.state}
    end
    backup backup_data
    remove_column :products, :state
  end
  def self.down
    add_column :products, :state, :string
    restore Product
  end
end
3

IIRC、移行でデータ型を変更すると、IrreversibleMigrationが発生します。

2
daustin777

大丈夫な別の状況は、統合された移行がある場合だと思います。その場合、すべてのテーブル(統合後に追加されたテーブルを除く)が削除されるため、「ダウン」は実際には意味がありません。それはおそらくあなたが望むものではありません。

0
dzajic