移行をスキップできるオプションや何かを見つけられないようです。
私はあなたが考えていることを知っています:「あなたはそれをする必要はないはずです...」
開発データベースに存在しない特定のユーザーレコードを変更する移行をスキップする必要があります。移行の対象となるソースの一部ではないため、移行を変更したくありません。移行をスキップする方法、または失敗した移行をスキップする方法はありますか?
前もって感謝します!
問題のある移行をより脆弱に修正する必要があると思います。いくつかの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
_」オプションのみを含めています。
既に存在するテーブルを追加するための移行があったという問題があったので、私の場合は、エラーが発生していたため、この移行もスキップする必要がありました
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
これは、1回限りのエラーに対して有効な方法です。
db:migrate:up VERSION=my_version
これにより、特定の移行の「アップ」アクションが実行されます。 (必要な場合は逆もあります。「上」を「下」に置き換えるだけです。)このように、古いもの(スキップする必要がある)を機能させる将来の移行を実行するか、それぞれを実行することができます。その先に選択的に移行します。
また、この方法で移行をやり直すことができると信じています。
rake db:migrate:redo VERSION=my_version
私は個人的にその方法を試したことがないので、YMMV。
欠落しているすべての移行を挿入します。
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) }
場合によっては、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"
-挿入を停止する前の移行のタイムスタンプです(空のままにしておくことができます)
!!!どの結果が得られるかを完全に理解している場合にのみ使用してください!!!
移行をスキップする代わりに、移行をスマートにし、IFを追加して、「特定のユーザー」を確認できます。
保留中の移行をすべてスキップするには、ターミナルでこれを実行します。
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。