移行の self.down メソッドで ActiveRecord::IrreversibleMigration 例外を発生させることが許容されるのはいつですか? 移行の逆を実際に実装するために、いつ努力する必要がありますか?
7 に答える
生産グレードのシステムを扱っている場合、はい、非常に悪いです。それがあなた自身のお気に入りのプロジェクトである場合は、何でも許されます (他に何もなければ、それは学習体験になります :) チャンスは遅かれ早かれ、ペットのプロジェクトであっても、逆移行は、数日後にその移行を元に戻す必要があるだけで、経由rake
または手動で行われます)。
運用シナリオでは、運用環境で実行する可能性がある場合に備えて、可逆的な移行を記述してテストするよう常に努力する必要があります。その後、(コードとスキーマ) を以前のリビジョン (保留中)にロールバックする必要があるバグを発見します。いくつかの重要な修正 -- およびそうでなければ使用できない実稼働システム。)
リバース マイグレーションは、ほとんど単純なもの (マイグレーション中に追加された列またはテーブルの削除、および/または列の型の変更など) から、やや複雑な ( execute
edJOIN
またはINSERT
sUPDATE
の) ものまでさまざまですが、「スイープする」ことを正当化するほど複雑なものはありません。じゅうたんの下」。少なくとも、リバース マイグレーションを実現する方法を考えるように強制することで、フォワード マイグレーションが解決しようとしている問題そのものについて新たな洞察を得ることができます。
フォワード マイグレーションによってフィーチャが削除され、その結果、データベースからデータが破棄されるという状況が発生する場合があります。 明らかな理由から、リバース マイグレーションでは破棄されたデータを復活させることはできません。yml
このような場合、完全な失敗 (に保存、特別なテーブルにコピー/移動など) の代替手段として、フォワード マイグレーションでデータを自動的に保存するか、ロールバックが発生した場合にデータを保持することをお勧めしますが、そうしないでください。このような自動化された手順をテストするのに必要な時間は、データを手動で復元するのに必要な時間を超える可能性があるため (必要が生じた 場合)、そうする必要はありません。条件付きで一時的にいくつかのユーザーアクションを保留して失敗します(つまり、手動で復元する必要がある必要なテーブルの存在をテストします。見つからない場合は、「何もないXYZ
ところからテーブルを再作成できないため、失敗しました。手動でXYZ
バックアップからテーブルを復元してから、もう一度実行してください。あなたを失望させません!」)
データを破棄する場合は、最初にバックアップを作成できます。例えば
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
運用シナリオでは、運用環境で実行する可能性がある場合に備えて、可逆的な移行を記述してテストするよう常に努力する必要があります。その後、(コードとスキーマ) を以前のリビジョン (保留中) にロールバックする必要があるバグを発見します。いくつかの重要な修正 -- およびそうでなければ使用できない実稼働システム。)
可逆的な移行は開発とステージングには問題ありませんが、十分にテストされたコードを想定すると、本番環境に移行したいと思うことはほとんどありません。本番モードでの自動 IrreversibleMigration を移行に組み込みます。本当に変更を元に戻す必要がある場合は、別の "up" 移行を使用するか、例外を削除できます。それは大ざっぱに思えますが。この悲惨なシナリオを引き起こす可能性のあるバグは、QA プロセスが深刻に失敗していることを示しています。
リバーシブル データ移行では、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
統合された移行がある場合も、問題ないと思います。その場合、「ダウン」は実際には意味がありません。すべてのテーブルが削除されるためです (統合後に追加されたテーブルを除く)。それはおそらくあなたが望むものではありません。