Rails6 usersテーブルにpasswordカラムが作成されなくて困った話

# 目的

- マイグレーションファイルの記載を間違えてコマンド`$ rails db:migrate`を実行してしまい、その後記載を正しいものにしてもpasswordカラムが作成されなかった時の解決方などをまとめる。

# 結論

- 一旦マイグレーションファイルを削除して再度マイグレーションファイルを作成し記載内容を確かめた上で`rails db:migrate`を実行した。
 
# 困りごとに至った経緯

1. 自作プロダクトでログイン機能を実装したい。
1. usersテーブルにはすでに`name`カラムと`email`カラムと初期設定カラムが作成されていたのでマイグレーションファイルを作成して`password`カラムの追加を行おうと思った。
1. コマンド`$ rails g migration add_password_to_users`を実行した。作成されたマイグレーションファイル名は「20191211134100_add_password_to_users.rb」である
1. マイグレーションファイルへの書き込みをしないままコマンド`$ rails db:migrate`を実行してしまう。
1. マイグレーションファイルに記載をしていないことが判明、下記の内容を記載するもコードミスをする。(add_columnのnがない)

     ```rb
     class AddPasswordToUsers < ActiveRecord::Migration[6.0]
        def change
          add_colum :users, :password, :string 
        end
     end
     ```

1. コードをミスっているマイグレーションファイルをコマンド`$ rails db:migrate`で反映させてしまう。
1. マイグレーションファイルのコードミスに気がつき、修正し再度コマンド`$ rails db:migrate`を実行した。
1. rails consoleにてusersテーブルのidが1のレコード情報をuserに格納しpasswordカラム情報を追記しようとしたところ下記のエラーが発生した。(passwordカラムなんて存在しないぜという感じのエラー)(エラーコード以外のrails console内での出力は省略)

    ```
    irb(main):001:0> user = User.find_by(id:1)
    irb(main):002:0> user.password = "0000"
    Traceback (most recent call last):
            1: from (irb):2
    NoMethodError (undefined method `password=' for #<User:0x00007fd0e2424fe0>)
    ```

# 解決までの経緯

1. 現在のテーブルのカラムがどうなっているか知りたかったので`アプリ名/db/schema.rb`を確認しに行った。下記に問題発生時のschema.rbを記載する。

    ```rb
    ActiveRecord::Schema.define(version: 2019_12_14_093144) do

      create_table "posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
        t.text "content"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
        t.decimal "study_time", precision: 10
        t.text "hash_tag"
      end

      create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
        t.string "name"
        t.string "email"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
      end

    end
    ```

1. 前述の結果からusersテーブルにpasswordカラムが存在していないことがわかる。
1. マイグレーションファイルが空状態やコードミス状態でのコマンド`$ rails db:migrate`の実行もありなんとなく原因がわかった。
1. すでに、データベースに反映させたマイグレーションファイルはGit登録してしまっているので当該コミットをrevertするかマイグレーションファイルを作り直して再度コマンド`$ rails db:migrate`を実行するか迷った。
1. マイグレーションファイルを再度作成し直してデータベースに反映させることにした。
1. 下記コマンドを実行して引っ掻き回してしまったマイグレーションファイルを削除する。

    ```terminal
    $ rm -rf アプリ名/db/migrate/20191211134100_add_password_to_users.rb
    ```
1. 下記コマンドを実行してマイグレーションファイルを再作成した。

    ```terminal
    $ rails g migration add_password_to_users
    ```
1. 作成されたマイグレーションファイルにミスがない様に記載をした。下記に正しいマイグレーションファイルの内容を記載する。

    ```rb
    class AddPasswordToUsers < ActiveRecord::Migration[6.0]
      def change
        add_column :users, :password, :string 
      end
    end
    ```

1. 下記コマンドを実行してマイグレーションファイルの内容をデータベースに反映させた。

    ```terminal
    $ rails db:migrate
    >== 20191214093144 AddPasswordToUsers: migrating 
    >===============================
    >-- add_column(:users, :password, :string)
    >-> 0.0144s
    >== 20191214093144 AddPasswordToUsers: migrated (0.0145s) 
    >======================
    ```

1. passwordカラムが追加されているか確かめるため`アプリ名/db/schema.rb`を確認しに行った。下記に問題発生時のschema.rbを記載する。

    ```rb
    ActiveRecord::Schema.define(version: 2019_12_14_093144) do

      create_table "posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
        t.text "content"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
        t.decimal "study_time", precision: 10
        t.text "hash_tag"
      end

      create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
        t.string "name"
        t.string "email"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
        t.string "password"
      end

    end
    ```

1. usersテーブル部分に`t.string "password"`の記載を発見したので無事passwordカラムが追加されていそう。
1. rails consoleをでusersテーブルのidが1のユーザのpasswordが登録できるか試してみた。(エラーコードは出なかったためrails console内での出力は省略)

    ```terminal
    $ cd アプリ名フォルダ
    $ rails console
    irb(main):001:0> user = User.find_by(id:1)
    irb(main):002:0> user.password = "0000"
    irb(main):003:0> user.save
    User Update (0.5ms)  UPDATE `users` SET `users`.`updated_at` = '2019-12-14 09:35:32.920487', `users`.`password` = '0000' WHERE `users`.`id` = 1
       (0.7ms)  COMMIT
    => true
    ```

1. 値をデータベースに保存する時にtrueが出たためpasswordカラムが作成され、正常に値も格納されたことを確認できた。
1. 今回の件にはあまり関係無いが、`アプリ名/app/models/user.rb`にpasswordカラムの空欄を弾く様にバリデーションを追記した。下記にuser.rbの内容を記載する。

    ```rb
    class User < ApplicationRecord
        validates :email, {presence: true, uniqueness: true}
        validates :name, {presence: true}
        validates :password, {presence: true}
    end
    ```