web-dev-qa-db-ja.com

失敗した移行をどのようにスキップしますか? (rake db:migrate)

移行をスキップできるオプションや何かを見つけられないようです。

私はあなたが考えていることを知っています:「あなたはそれをする必要はないはずです...」

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

前もって感謝します!

39
hmind

問題のある移行をより脆弱に修正する必要があると思います。いくつかのifステートメントとおそらくrescueで十分だと思います。

しかし、移行を修正することが実際に選択肢ではない場合、さまざまな方法でそれを偽造することができます。まず、移行方法をコメントアウトし、_rake db:migrate_を実行してから、問題のある移行のコメントを外す(または元に戻す)ことができます。

データベース内で偽装することもできますが、この種の詐欺は、自分が何をしているのかがわからない場合や、(間違いなく)間違いを犯したときに手動でパッチを適用することを気にしない限りお勧めできません。データベースには、versionという単一のvarchar(255)列を持つ_schema_migrations_というテーブルがあります。このテーブルは_db:migrate_によって使用され、どの移行が適用されたかを追跡します。必要なことは、適切なversion値を挿入するだけで、_rake db:migrate_は移行が完了したと判断します。問題のある移行ファイルを見つけます。

_db/migrate/99999999999999_XXXX.rb
_

次に、データベースにアクセスして次のように言います。

_insert into schema_migrations (version) values ('99999999999999');
_

ここで、_99999999999999_は、もちろん、移行のファイル名からの番号です。その後、_rake db:migrate_を実行すると、その移行はスキップされます。

3番目の前に2番目のオプションを使用します。完全を期すために、「hack _schema_versions_」オプションのみを含めています。

59
mu is too short

既に存在するテーブルを追加するための移行があったという問題があったので、私の場合は、エラーが発生していたため、この移行もスキップする必要がありました

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

Create tableメソッドの内容をコメントアウトし、移行を実行し、コメントを外しました。手動で回避する方法ですが、機能しました。下記参照:

class CreatePosts < ActiveRecord::Migration
  def change
    # create_table :posts do |t|
    #   t.string :title
    #   t.text :message
    #   t.string :attachment
    #   t.integer :user_id
    #   t.boolean :comment
    #   t.integer :phase_id

    #   t.timestamps
    # end
  end
end
16
user1647964

これは、1回限りのエラーに対して有効な方法です。

db:migrate:up VERSION=my_version

これにより、特定の移行の「アップ」アクションが実行されます。 (必要な場合は逆もあります。「上」を「下」に置き換えるだけです。)このように、古いもの(スキップする必要がある)を機能させる将来の移行を実行するか、それぞれを実行することができます。その先に選択的に移行します。

また、この方法で移行をやり直すことができると信じています。

rake db:migrate:redo VERSION=my_version

私は個人的にその方法を試したことがないので、YMMV。

15
John

それが必要な場合、アプリの移行が台無しになります!

欠落しているすべての移行を挿入します。

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) }
7
Dorian

場合によっては、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

コピーして任意のモデルに貼り付け、コンソールから使用できます

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx")

(または何らかの方法で)

どこ "xxxxxxxxxxxxxx"-挿入を停止する前の移行のタイムスタンプです(空のままにしておくことができます)

!!!どの結果が得られるかを完全に理解している場合にのみ使用してください!!!

1
okliv

移行をスキップする代わりに、移行をスマートにし、IFを追加して、「特定のユーザー」を確認できます。

1
Alessandro DS

保留中の移行をすべてスキップするには、ターミナルでこれを実行します。

echo "a = [" $(Rails db:migrate:status | grep "down" | grep -o '[0-9]\{1,\}' | tr '\n' ', ') "];def insert(b);ActiveRecord::Base.connection.execute(\"insert into schema_migrations (version) values (#{b})\") rescue nil;end;a.map { |b| insert(b)}" | xclip

(macOSの場合、xclipではなくpbcopyを使用します)

次に、CTRL-Vで結果をRails console:

a = [ 20180927120600,20180927120700 ];def insert(b);ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{b})") rescue nil;end;a.map { |b| insert(b)}

Enterキーを押します。

スキップする移行のリストを変更するには、行を実行する前にアレイからそれらを削除しますa

0
Tim N