【Rails】なぜマイグレーションファイルを変更した後にrails db:migrateで修正が反映されないのか?マイグレーションが実行されない時の対処法

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

Railsでマイグレーションを行った後に、ちょっとだけ修正を加えたいと思ってマイグレーションファイルを直接編集することがあるかもしれません。

そうしたときにマイグレーションファイルを直接変更した後でrails db:migrateをしても変更は反映されません。

ここでは、なぜマイグレーションファイルを直接変更したときに、マイグレーションが再度実行できないのか?どうすれば変更を反映できるのかについてまとめています。


なぜマイグレーションできないのか?(変更が反映されないのか?)

マイグレーションファイルを直接変更した場合にマイグレーションが実行されない理由は、マイグレーションの現在のバージョンとファイルが一致しているため、既にマイグレーション済みと判断されてしまうためです。

Railsの公式ガイドにも次のような記載があります。

いったんマイグレーションを実行してしまった後では、既存のマイグレーションを単に編集してもう一度マイグレーションをやり直しても意味がありません。Railsはマイグレーションが既に実行済みであると認識しているので、rails db:migrateを実行しても何も変更されません。

Active Record マイグレーション:https://railsguides.jp/active_record_migrations.html


マイグレーションとは何なのか?

そもそもですが、マイグレーションとは、データベースを直接操作することなく、データベースの構造(スキーマ)を変更する仕組みです。

簡単な流れでみると以下のようになります。

  1. 最初スキーマは空の状態です。
  2. マイグレーションファイルを作成して、マイグレーションを実行するとデータベースに指定したにスキーマが生成されます。
  3. このとき、バージョン管理ようのテーブルも自動生成され、その中でどのマイグレーションファイルまでを実行したかが記録されます。
  4. 新しいマイグレーションを実行する毎にバージョン追加されていきます。

このようにバージョン(履歴)管理をしているため、特定のマイグレーションを取り消して過去の状態に戻すこともできます。

合わせて読みたい

Railsがどのようにマイグレーションのバージョンを管理しているかについては下記をご参考ください。

【Rails】ロールバック(rollback)で何が起こっているか?schema_migrationsとは?意味と役割。UPとDOWNとは?それぞれの使い方


対処法

対処は簡単です。ロールバックを使って、マイグレーションファイルの状態を実行前「down」の状態に戻してあげれば、再度rails db:migrateでマイグレーションを実行できるようになります

こういったときは、マイグレーションのバージョンを戻せば再度実行できます。ここでその方法について解説しています。

なお対処法は1つではなくいくつかあります。

対処法
  1. rails db:rollbackでロールバックを実行する。
  2. rails db:migrate:redoを使う。
  3. rails db:resetを使う。
  4. 新しいマイグレーションファイルを作成する。


rails db:rollbackでロールバックを実行する

ロールバックはrails db:rollbackで実行できます。

rails db:rollbackは直近の実行済みのマイグレーションファイルの内容を一つだけ見実行に戻します。

rails db:migrateと合わせて実行すれば、マイグレーションが実行できます。

$rails db:rollback
$rails db:migrate

なお、$rails db:rollback STEP=数値にすると指定した数の分だけマイグレーションファイルが前の状態に戻ります。


rails db:migrate:redoを使う

2つ目の対処法はRailsにはロールバックとマイグレーションを同時に実行できるrails db:migrate:redoコマンドを使うことです。

$rails db:migrate:redo

これは以下のコマンドと同じです。

$rails db:rollback
$rails db:migrate


rails db:resetを使う

データベースのスキーマを完全にリセット(空っぽにする)する。rails db:resetを使う方法もあります。

rails db:resetを実行しても、マイグレーションファイルは残るので、再度マイグレーションすれば、新しいファイルの内容でスキーマができあがります。

ただし、データがなくなるので非推奨です。逆に、データも全部リセットして作り直したいという場合はこれを使うべきです。

$rails db:reset
$rails db:migrate

なお、db:resetコマンドは、db:dropでDBを削除して、db:setupで再設定しているのと同じ処理になります。


新しいマイグレーションファイルを作成する

既存のファイルを編集するのではなく、おとなしく、変更を加えた新しいマイグレーションファイルを作成するのも効果的な対処法です。

とくに、他の人たちと共同開発しているプロジェクトの場合は、マイグレーションファイルを直接書き変えると、他の人が持っている中身と合わなくなり、コンフリクトが発生するといった弊害があるので、修正を加えたマイグレーションファイルを新たに作成するのが一般的です。

手順は以下のようになります。

マイグレーションファイルを新規作成する

まずはマイグレーションファイルを新規作成します。

$ rails g migration マイグレーションクラス名

次の処理で、元ファイルをコピペするのでカラムや型は特に指定する必要はありません。

もし、指定したい場合は以下のように引数を与えます。

$ rails g migration マイグレーションクラス名 カラム名:型,,,


マイグレーションファイルを編集する

生成したマイグレーションファイルに以前のスキーマをコピペして、編集します。


マイグレーションを実行する

新たに作成したマイグレーションファイルの内容をデータベースに反映させるため、マイグレーションを実行します。

$ rails db:migrate

以上で変更内容の反映が完了します。


(補足)マイグレーションバージョンや履歴の確認方法

マイグレーション履歴の確認方法

マイグレーション履歴を確認するにはrake db:migrate:statusを実行します。

上が古く、下が新しいものです。

# rake db:migrate:status

database: rails_screamer_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20110521181506  Create pages
   up     20110521182915  Create categories
   up     20110703120321  Add position to pages
   up     20110716180121  Add position to categories
  down    20110724110158  Add english name to categorydevise

なお、一番左端の「up」はマイグレーション済み(DBに適用済み)、「down」はマイグレーション見実行(DB適用前)という状態を表しています。

$rails db:rollbackを実行すると直近の「up」が「down」になります。


現在の最新のマイグレーションバージョンの確認

現在の最新のマイグレーションバージョンの確認するには、rails db:versionを実行します。

# rails db:version
Current version: 20110716180121


合わせて読みたい

マイグレーションしたときとロールバックしたときで処理を切り分ける方法(changeとdownメソッド)など、ロールバックの詳細が知りたい方は下記をご参考ください。

【Rails】ロールバック(rollback)で何が起こっているか?schema_migrationsとは?意味と役割。UPとDOWNとは?それぞれの使い方


タイトルとURLをコピーしました