9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

初心者目線のmigrationまとめ(1)【migration消しちゃった?!】

Last updated at Posted at 2023-04-20

初心者の俺 「migrationを……」

消したいけど、どうしたらいいんよ?!

migrationのここが大切

  • migrationとは、直接SQLを使わずにデータベースのテーブルやカラムなどの構造(スキーマ)を変更できる仕組み
  • migrationファイルを新しく作ったら、rails db:migrateしないとActiveRecord::PendingMigrationErrorエラーになる
  • migrationファイルは更新履歴みたいなもの。好き勝手に消したり付け加えてはいけない。いいか、好き勝手に消したり付け加えてはいけないぞ!そこの俺、聞いてるか?!

じゃあどうやって修正するの?

方法は2つ。

1.migrationファイルを新たに作成し、上書きする(推奨)

2.migrationの適用を戻すコマンドを使い、修正する

1と2を説明する前に……

そもそも、migrationファイルでDBを更新する流れをおさらい

知ってる人は次の項目へスキップ:runner_tone3:

①最初、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ファイル↓

db/migrate/20230420103137_add_age_to_user.rb
class AddAgeToUser < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :age, :integer
  end
end

ここで、schema.rbとmigrationファイルの状態がどうなっているか見てみます。

db/schema.rb
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にも反映されていないことが分かります。

サーバも見てみましょう。
スクリーンショット 2023-04-20 19.45.53.png
エラーがでてます。

では、張り切っていってみましょう
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テーブルにバージョンが保存されているためです。
スクリーンショット 2023-04-20 21.22.49.png
このレコードを削除すれば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

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?