2012-01-10 15 views
31

私はオプションや、マイグレーションをスキップできるものは見つかりません。失敗した移行をどのようにスキップしますか? (rake db:migrate)

私は何を考えている知っている:「あなたはそれをしなければならないことはありません...」

を、私は私の開発データベースに存在しない特定のユーザーレコードの変更を行い、移行をスキップする必要があります。私は、私が作業しているはずのソースの一部ではないので、移行を変更したくないです。移行をスキップしたり、失敗した移行をスキップする方法はありますか?

ありがとうございます!

答えて

53

私はあなたが壊れにくくなるために、問題の移行を修正する必要があり、私はif文、おそらくrescueのカップルは十分だろうと推測すると思います。

しかし、実際に移行を修正することはオプションではない場合は、さまざまな方法で偽装することができます。まず、移行方法をコメントアウトしてrake db:migrateを実行して問題のある移行のコメントを外す(または元に戻す)ことができます。

また、データベース内で偽装することもできますが、あなたが何をしているのか分からない限り、手動でパッチを当てても間違いがない限り、この種の攻撃はお勧めしません。データベースにschema_migrationsというテーブルがあり、varchar(255)という単一の列がversionとなっています。この表はdb:migrateによってどの移行が適用されたかを追跡するために使用されます。あなたがする必要があるのは、適切なversionの値を挿入することと、rake db:migrateは、移行が完了したと考えるでしょう。あなたのデータベースに行くと言って、その後

db/migrate/99999999999999_XXXX.rb 

99999999999999は、当然のことながら、移行のファイル名の数であり
insert into schema_migrations (version) values ('99999999999999'); 

を問題の移行ファイルを検索します。その後、rake db:migrateを実行すると、その移行はスキップされます。

3番目の前に2番目のオプションを使用していますが、完全性のために「ハックschema_versions」オプションを含めるだけです。

+0

雅、私は先に行って、一時的に問題の移行を切り出します。私は個人的には適切なIf文を作成していたか、それとも実動環境をチェックしていたのでしょうか?明らかに、マイグレーションを処理する人はdbを使用することを信じていません:Pの開発中にマイグレーションしてくださいThanks – hmind

+0

@hmind:マイグレーションはdb:migrateを開発中に使用することを信じていません。 "ああ、私。あなたのプロダクションシステムへの公開は、楽しい楽しい時間でなければなりません! –

+2

幸運にも、私はそれを扱っていませんどちらかというとhaha – hmind

1

の代わりに、あなたが

+0

そうです、それは私が移行を書いたならば私がやったことです。しかし、私はしなかったし、私は本当に触れてはいけないソースの一部で回りたいので、私はちょうどそれらを一時的に切って終わった。 – hmind

14

を「特定のユーザー」をチェックすることができますので、これは一回限りのエラーのためにそれを行うには良い方法ですが、それにいくつかのIFを追加し、あなたの移行は、スマート作ることができるの移行をスキップします。

db:migrate:up VERSION=my_version

これは、1つの特定のマイグレーションの "アップ" のアクションを実行します。 (これを必要とする場合は逆もありますが、単に "up"を "down"に置き換えてください)。このようにして、古いもの(スキップする必要があるもの)を動作させる将来の移行を実行するか、それを先取りして選択的に移行する。

私はまた、あなたが移行をこのようにやり直すことができると信じている:

rake db:migrate:redo VERSION=my_version

私はYMMVので、個人的にその方法を試していません。

1

時には、間違いなく正しい移行 ...とschema_migrationsテーブルを再充填する必要がある、私はあなたにそれをコピー&ペーストすることができ、この方法

def self.insert_missing_migrations(stop_migration=nil) 
    files = Dir.glob("db/migrate/*") 
    timestamps = files.collect{|f| f.split("/").last.split("_").first} 
    only_n_first_migrations = timestamps.split(stop_migration).first 

    only_n_first_migrations.each do |version| 
    sql = "insert into `schema_migrations` (`version`) values (#{version})" 
    ActiveRecord::Base.connection.execute(sql) rescue nil 
    end 
end 

を作成しているONLYこの目的 FOR あなたがしたいと任意のモデルには、コンソールから、それを使用

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx") 

(または何らかの形で他の)

"xxxxxxxxxxxxxx"は - あなたが挿入を停止したいの前に、移行のタイムスタンプ(あなたは空のままにすることができます)

です!どんな結果が得られるかを絶対に理解している場合にのみ使用してください!私は単に

SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts" 

エラーを得ていたので、私の場合、私は、同様にこの移行をスキップしなければならなかったので、

10

私は、私はすでに存在していたテーブルを追加するための移行を持っていた問題がありましたcreate tableメソッドの内容をコメントアウトし、移行を実行してコメントを外しました。それを回避する手作業のようなものですが、うまくいきました。下記を参照してください:

​​
+0

これは素晴らしいです!私はこれについて考えなかったとは信じられません。完全に働いた。 – helpse

7

あなたがする必要がある場合、あなたのアプリの移行が台無しです!

挿入不足しているすべての移行:

def insert(xxx) 
    ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil 
end 

files = Dir.glob("db/migrate/*") 
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) } 
+1

必ずしもそうではありません。たとえば、本番データベースを開発マシンにpg_restoreして、運用データの問題のトラブルシューティングを行う場合などです。あなたがすべての情報を持っていないときに間違ってやっていると誰かに伝えるのが素早くしないでください。 –

+0

@MikeBethany:私の場合は、それを使用しなければならない時がありました。すべてが大混乱でした。なぜそれがどうなったのか理解する時間はありませんでした。 pg_restoreについては、 'schema_migrations'テーブルも復元する必要があります。 – Dorian

+0

もちろん、schema_migrations'テーブルはデータベース内の単なるテーブルに過ぎません。あなたのタイトルを再読する私は別の解釈を見ることができます。私はもともと「あなたは適切に移行を書いていない」と読んでいました。私があなたが実際に意味することは、「マイグレーションに問題があります。しかし、それは明らかです。それゆえの質問です。だから私はあなたが "悩んだ"という意味を仮定しました。私の悪い。 –

関連する問題