マイグレーションの仕組みと流れ
マイグレーションを行う際に、3つのファイルが実行される。
■マイグレーションファイル
データベースに対して行いたい変更を記述するもの
■スキーマファイル(schema.rb)
現状のデータベースの状態を保存するもの
■データベース
◆流れ
1. マイグレーションファイルに変更内容を書く
2. マイグレーションを実行(db:migrate)することで、データベースの内容が変更される
3. 変更された内容のデータベースの状態で、schema.rbが更新される
4. schema.rbのタイムスタンプが更新される
マイグレーションファイル作成
■新規でモデルから作成し、マイグレーションファイルも作成する場合。
rails g model モデル名 追加するカラム名:型(カラムは後でも書けるのでどちらでも)
# 例
rails g model user name:string age:integer
ここでrails db:migrateを行うと、マイグレーションファイルが生成される。
(今回はname:string age:integer 無しのモデルに何も編集していない状態で進める。)
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps
end
end
end
カラムを無しで作成するとt.timestampsのみがデフォルトで記載されている。
それにより、作成日時を意味するcreated_atと、更新日時を意味するupdated_atがカラムに追加される。
■モデルは既にあって、カラムを追加したいからマイグレーションファイルだけ作成する場合。
rails g migration Add 追加するカラム名 To 追加するテーブル名 追加するカラム名:型(カラムは後でも書けるのでどちらでも)
# 例
rails g migration AddEmailToUsers email:string
あとはバリデーションを追記するなりしてrails db:migrateをすればカラムが追加される。ただし追加だけでなく既にあるファイルを変更となると、ファイルのステータスから見ないといけない。
マイグレーションファイルのステータス
マイグレーションファイルにはステータスが存在する。
ステータスはrails db:migrate:statusコマンドで確認できる。
$ rails db:migrate:status
Status Migration ID Migration Name
--------------------------------------------------
up 20190501111550 Create blogs
up 20190501123505 Change blogs title not null
down 20190501123715 Change blogs content not null
down 20190502033857 Create comments
このステータス画面では、どのマイグレーションファイルが実行中で、どのファイルが実行されていないかが分かる。
upが実行中で、downが実行されていない状態である。
マイグレーションを実行(db:migrate)することで、up状態になる。
このマイグレーションファイルのup/downの状態が重要になってくる。
例えば、マイグレーションファイルの変更を行いたいときなどにステータスの有無が必要になってくる。
マイグレーションファイルの変更を行う場合
仮にuserテーブルにカラムを追加・変更を実施する際に、マイグレーションファイルのステータスを**down**にしなければならない。
up状態で、マイグレーションファイルに変更を加えて、rails db:migrateを実施しても全く反映されない。(装備中の防具を外さないと新しい装備が付けれない的な)
down状態にするには、コマンドでrails db:rollbackを実行すればできる。変更を施した後、またrails db:migrateを行えばup状態になる。
⚠️注意
マイグレーションファイルは基本的に上から(時間順)に実行されていく。rollbackは反対の下から(最新時間順)から1個のファイルのみdownになるので、変更したいファイルまで飛ばしたい場合にはSTEP数を指定してロールバックする。もしくはMigration IDを指定して行う。
# STEP数を指定してロールバック
$ rails db:rollback STEP=ステップ数
# Migration IDを指定してロールバック。IDはステータスで確認できる。
$ rails db:migrate:down VERSION=oooooooooo
up状態のマイグレーションのファイルを削除すると「NO FILE」ができる
もし不要なマイグレーションファイルがあって削除する場合、down状態で削除したらいいが、up状態のまま消してしまうと以下のようになる。
Status Migration ID Migration Name
--------------------------------------------------
up 20190915023701 Create posts
up 20190915065320 ********** NO FILE **********
down 20190915080932 Devise create users
このNO FILEを削除する方法として、ダミーファイルを作成し、そのファイルを削除することで解決する。
Migration IDをコピーしてダミーファイルを作成。(名前は適当でOK)
touch db/migrate/20190915065320_hoge.rb
ダミーファイルが作成できたら、ちゃんとNO FILEだったところに割り当てられているか確認する。
Status Migration ID Migration Name
--------------------------------------------------
up 20190915023701 Create posts
up 20190915065320 Hoge
down 20190915080932 Devise create users
確認できたら、このダミーファイルをdown状態にし、削除すれば良い。
$ rails db:migrate:down VERSION=20190915065320
$ rm db/migrate/db/migrate/20190915065320_hoge.rb
コマンド集
マイグレーション関連コマンド集
| コマンド | 意味・機能 |
|---|---|
| rails g migration クラス名 | マイグレーションファイル作成 |
| rails g model モデル名 | モデル作成 |
| rails db:migrate | マイグレーション実行 |
| rails db:migrate:status | ステータス確認 |
| rails db:rollback | ロールバック |
| rails db:rollback STEP=ステップ数 | STEP数を指定してロールバック |
| rails db:reset | 全てのDBを削除した後に、schema.rbを元にDB作成 |
| rails db:migrate:reset | 全てのDBを削除した後に、db/migrate/**.rb を元に古い順から実行 |
参考記事
Ruby on Rails 『NO FILEのmigrationを削除する方法』
[Rails]マイグレーションファイルについて勉強してみた!(テーブルへのカラム追加)
Rails:マイグレーションファイル、スキーマファイル におけるタイムスタンプの役割
rails generate migrationコマンドまとめ
rails db:migrate:resetできなかったのでrails db:resetした