初心者の俺 「migrationを……」
消したいけど、どうしたらいいんよ?!
migrationのここが大切
- migrationとは、直接SQLを使わずにデータベースのテーブルやカラムなどの構造(スキーマ)を変更できる仕組み
- migrationファイルを新しく作ったら、
rails db:migrate
しないとActiveRecord::PendingMigrationError
エラーになる - migrationファイルは更新履歴みたいなもの。好き勝手に消したり付け加えてはいけない。いいか、好き勝手に消したり付け加えてはいけないぞ!そこの俺、聞いてるか?!
じゃあどうやって修正するの?
方法は2つ。
1.migrationファイルを新たに作成し、上書きする(推奨)
2.migrationの適用を戻すコマンドを使い、修正する
1と2を説明する前に……
そもそも、migrationファイルでDBを更新する流れをおさらい
知ってる人は次の項目へスキップ
①最初、DBの構造(スキーマ)は空の状態
②マイグレーションファイルを作成して、DBの変更内容を書く。
③rails db:migrate
を実行するとDBに指定したスキーマが生成される。
このとき、バージョン管理用のテーブルも自動生成され、その中でどのマイグレーションファイルまでを実行したかが記録される。
④新しいマイグレーションを実行する毎にバージョンが追加されていく。
マイグレーションファイルでDBの設計図を書いて、rails db:migrate
で実際にDBを操作するイメージ。
ちょっと違うかもだけど、Amazonでカートに物入れた状態がマイグレーションファイル書いた状態で、実際購入ボタン押すのがrails db:migrate
。購入履歴を操作しようとしてもできなくて、一回キャンセルしたり、もう一度改めて注文しないと変更できないあの感じに似ている。(絶対に違う)
では、本題に戻る。
1.migrationファイルを新たに作成し、上書きする(推奨)
推奨理由
複数人で開発した時に、好き勝手DBをいじれてしまうと混乱するため。migrationファイルが一度rails db:migrate
したら基本的に変更を受け付けないのも、時系列で変更を管理することで、DBの変更に矛盾が起きないようにしている仕組みだから。
実際の修正方法
下記のusersテーブルにageカラムを追加してみる。
users |
---|
id : integer |
name : string |
email : text |
①まずはmigrationファイルを新規作成
#rails generate migration ファイル名 [カラム名:型[:index]]
rails generate migration AddAgeToUser age:integer
migrationファイルは更新履歴の代わりになるものなので、何の変更を加えたか分かりやすい名前をつけます。
上記コマンドを打った結果作成されたmigrationファイル↓
class AddAgeToUser < ActiveRecord::Migration[7.0]
def change
add_column :users, :age, :integer
end
end
ここで、schema.rbとmigrationファイルの状態がどうなっているか見てみます。
ActiveRecord::Schema[7.0].define(version: 2023_04_20_103042) do
create_table "users", force: :cascade do |t|
t.string "name"
t.text "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
$ rails db:migrate:status
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
down 20230420103137 Add age to user
まだmigrationファイルは適用されておらず(downの状態)、schema.rbにも反映されていないことが分かります。
では、張り切っていってみましょう
rails db:migrate
このコマンドめっちゃ好き……
ActiveRecord::Schema[7.0].define(version: 2023_04_20_103137) do
create_table "users", force: :cascade do |t|
t.string "name"
t.text "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "age"
end
end
$ rails db:migrate:status
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
up 20230420103137 Add age to user
upになっている状態のmigrationファイルに変更を加えてrails db:migrate
コマンドを打っても変更されません。
では、これをdown状態に戻すのはどうしたらいいでしょうか?
2.migrationの適用を戻すコマンドを使い、修正する
個人開発やrails db:migrate
を実行してすぐの変更であればこちらも便利
直前のrails db:migrate
を取り消す
rails db:rollback
実行後の状態
$rails db:migrate:statu
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
down 20230420103137 Add age to user
指定のマイグレーションファイルまで戻す
分かりやすくするためにmigrationファイルを追加しました。
$ rails db:migrate:status
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
up 20230420103137 Add age to user
up 20230420113934 Add password to user
up 20230420114101 Add avatar to user
up 20230420114254 Remove avatar to user
方法が3つあります
①rails db:rollback
を繰り返し、1つずつ戻っていく
②rails db:rollback STEP=n
# 例:3つ前まで戻る
$ rails db:rollback STEP=3
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
up 20230420103137 Add age to user
down 20230420113934 Add password to user
down 20230420114101 Add avatar to user
down 20230420114254 Remove avatar to user
③戻るマイグレーションファイルのバージョンを指定する
rails db:migrate:down VERSION= Migration ID
# Add age to userのファイルを戻す
$ rails db:migrate:down VERSION= 20230420103137
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
down 20230420103137 Add age to user
up 20230420113934 Add password to user
up 20230420114101 Add avatar to user
up 20230420114254 Remove avatar to user
俺へ
これやって整合性無くなってエラー吐きまくってわけわからないことになって結局DBリセットしたのでおすすめしないよ
俺より
🙋♂️「先生、upのmigrationファイル消しちゃいました」
何だと?!好き勝手に消したり付け加えてはいけないってdifっJ陽gJrg子;g自vdsm素fkgお@!!!!!!!!
upのmigrationファイルを消すとどうなるか
→ *** NO FILE ***と表示される
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
up 20230420103137 Add age to user
up 20230420113934 Add password to user
up 20230420114101 Add avatar to user
up 20230420114254 ********** NO FILE **********
NO FILEと表示されるのはrails db:migrateした時にschema_migrationsテーブルにバージョンが保存されているためです。
このレコードを削除すればNO FILEの表示は消えますが、基本的には削除するのは良くないぽい。削除したファイル自体を戻すなどして対応した方が良いと思います。
downしたファイルは消しても大丈夫です。
$ rails db:rollback
$ rails db:migrate:status
Status Migration ID Migration Name
--------------------------------------------------
up 20230420103042 Create users
up 20230420103137 Add age to user
up 20230420113934 Add password to user
up 20230420114101 Add avatar to user
参考にしたもの
https://railsguides.jp/active_record_migrations.html
https://qiita.com/s_tatsuki/items/3e1f119c91e21b8f0c33
https://pikawaka.com/rails/migration