【Rails】テーブルのカラムを追加する

こんにちは。
早く駆け出したい修行僧です。

勉強用アプリにてカラムを追加する方法を
学んだので、アウトプットしていきます。

尚、「それは違うよ」など訂正箇所がございましたら、
愛のあるご指摘を頂けたら幸いです。

## 環境
MacBook Air(M1,2020) Monterey 12.2.1
Ruby 3.1.0
Rails 6.1.4.6
PostgreSQL 14.2

## 何をしたいか？

まずは、`foods`テーブルに`string`型の`image`カラムを追加したい。

## 現状のテーブルとカラム

追加前の`foods`テーブルとカラムは以下の通りです。

```:terminal
   Column   |              Type              | Collation | Nullable | 
------------+--------------------------------+-----------+----------+--
 id         | bigint                         |           | not null |
 user_id    | bigint                         |           | not null | 
 name       | character varying              |           | not null | 
 comment    | text                           |           |          | 
 created_at | timestamp(6) without time zone |           | not null | 
 updated_at | timestamp(6) without time zone |           | not null | 
```

## カラムを追加する

カラムを追加する前に注意点があります。
それは <font color='red'> 既存のマイグレーションファイルを直接編集しないことです。 </font>
既存のマイグレーションファイルを編集して`rails db:migrate`としても何も変更が加えられません。なぜなら、Railsは既にマイグレーションを実施したと認識しているからです。
以下、Railsガイドにて記載があります。

> 一般に、既存のマイグレーションを直接変更するのはよくありません。既存のマイグレーションを変更すると、自分自身はもちろん、共同作業者も余分な作業を強いられます。さらに、既存のマイグレーションがproduction環境で実行中の場合、ひどい頭痛の種になるでしょう。既存のマイグレーションを直接修正するのではなく、修正用のマイグレーションを新たに作成してそれを実行するのが正しい方法です。これまでコミットされてない（より一般的に言えば、これまでdevelopment環境以外にデプロイされたことのない）マイグレーションを新たに生成し、それを編集するのが害の少ない方法です。
> [Railsガイド](https://railsguides.jp/active_record_migrations.html#%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)

では、どうしたら良いのでしょうか。
ジェネレータでマイグレーションを新たに作成すれば良いですね。
以下のコマンドを実行します。（今回は`foods`テーブルに`string`型の`image`カラムを追加）

```:terminal
$ rails g migration AddImageToFoods image:string

#=> rails g migration Addカラム名Toテーブル名 カラム名:データ型
```

実行すると以下のファイルが作成されます。

```:terminal
Running via Spring preloader in process 3701
      invoke  active_record
      create    db/migrate/生年月日_add_image_to_foods.rb

```

## カラム追加後の状態

では、実際のファイルの中身はどうなっているでしょうか。
まずは新しく作成されたマイグレーションファイルを見ていきましょう。

```ruby:db/migrate/生年月日_add_image_to_foods.rb
class AddImageToFoods < ActiveRecord::Migration[6.1]
  def change
    add_column :foods, :image, :string
  end
end
```

こうですね。しっかりと`foods`テーブルに`image`カラムが追加されていることがわかります。
`NOTNULL`制約などのバリデーションを追加する必要があれば実施してしまいましょう。今回は追加する予定はないので省略します。

## マイグレーションの実施

ファイルの確認と各種編集が終わったらマイグレーションを実施しましょう。
以下のような表示がされていれば成功です。

```
$ rails db:migrate

== 20220307002415 AddImageToFoods: migrating ==================================
-- add_column(:foods, :image, :string)
   -> 0.0108s
== 20220307002415 AddImageToFoods: migrated (0.0109s) =========================

```

では、スキーマを見ていきましょう。

```diff_ruby:db/schema.rb
create_table "foods", force: :cascade do |t|
  t.bigint "user_id", null: false
  t.string "name", null: false
  t.text "comment"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
+ t.string "image"
  t.index ["user_id"], name: "index_foods_on_user_id"
end
```

こうですね。スキーマで`image`カラムが追加されています。
最後にターミナルでもテーブルの状態がどうなっているか見てみましょう。


```:terminal
   Column   |              Type              | Collation | Nullable | 
------------+--------------------------------+-----------+----------+--
 id         | bigint                         |           | not null |
 user_id    | bigint                         |           | not null | 
 name       | character varying              |           | not null | 
 comment    | text                           |           |          | 
 created_at | timestamp(6) without time zone |           | not null | 
 updated_at | timestamp(6) without time zone |           | not null | 
 image      | character varying              |           |          | 

```

先ほどまでは、`updated_at`までしかありませんでしたが、`image`カラムが追加されていることがわかりますね。

お疲れ様です！
最後までお読みいただきありがとうございました。

## 参考

[Railsガイド](https://railsguides.jp/active_record_migrations.html#%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
[Ruby on Rails カラムの追加と削除 - @azusanakano さん](https://qiita.com/azusanakano/items/a2847e4e582b9a627e3a)
[Railsでデータベースカラムの追加を行う方法 - @ryosuketter さん](https://qiita.com/ryosuketter/items/1aba45161bfffefed68b)