目的
- マイグレーションファイルの記載を間違えてコマンド
$ rails db:migrate
を実行してしまい、その後記載を正しいものにしてもpasswordカラムが作成されなかった時の解決方などをまとめる。
結論
- 一旦マイグレーションファイルを削除して再度マイグレーションファイルを作成し記載内容を確かめた上で
rails db:migrate
を実行した。
困りごとに至った経緯
-
自作プロダクトでログイン機能を実装したい。
-
usersテーブルにはすでに
name
カラムとemail
カラムと初期設定カラムが作成されていたのでマイグレーションファイルを作成してpassword
カラムの追加を行おうと思った。 -
コマンド
$ rails g migration add_password_to_users
を実行した。作成されたマイグレーションファイル名は「20191211134100_add_password_to_users.rb」である -
マイグレーションファイルへの書き込みをしないままコマンド
$ rails db:migrate
を実行してしまう。 -
マイグレーションファイルに記載をしていないことが判明、下記の内容を記載するもコードミスをする。(add_columnのnがない)
class AddPasswordToUsers < ActiveRecord::Migration[6.0] def change add_colum :users, :password, :string end end
-
コードをミスっているマイグレーションファイルをコマンド
$ rails db:migrate
で反映させてしまう。 -
マイグレーションファイルのコードミスに気がつき、修正し再度コマンド
$ rails db:migrate
を実行した。 -
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>)
解決までの経緯
-
現在のテーブルのカラムがどうなっているか知りたかったので
アプリ名/db/schema.rb
を確認しに行った。下記に問題発生時のschema.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
```
-
前述の結果からusersテーブルにpasswordカラムが存在していないことがわかる。
-
マイグレーションファイルが空状態やコードミス状態でのコマンド
$ rails db:migrate
の実行もありなんとなく原因がわかった。 -
すでに、データベースに反映させたマイグレーションファイルはGit登録してしまっているので当該コミットをrevertするかマイグレーションファイルを作り直して再度コマンド
$ rails db:migrate
を実行するか迷った。 -
マイグレーションファイルを再度作成し直してデータベースに反映させることにした。
-
下記コマンドを実行して引っ掻き回してしまったマイグレーションファイルを削除する。
$ rm -rf アプリ名/db/migrate/20191211134100_add_password_to_users.rb
-
下記コマンドを実行してマイグレーションファイルを再作成した。
$ rails g migration add_password_to_users
-
作成されたマイグレーションファイルにミスがない様に記載をした。下記に正しいマイグレーションファイルの内容を記載する。
class AddPasswordToUsers < ActiveRecord::Migration[6.0] def change add_column :users, :password, :string end end
-
下記コマンドを実行してマイグレーションファイルの内容をデータベースに反映させた。
$ rails db:migrate >== 20191214093144 AddPasswordToUsers: migrating >=============================== >-- add_column(:users, :password, :string) >-> 0.0144s >== 20191214093144 AddPasswordToUsers: migrated (0.0145s) >======================
-
passwordカラムが追加されているか確かめるため
アプリ名/db/schema.rb
を確認しに行った。下記に問題発生時のschema.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
```
-
usersテーブル部分に
t.string "password"
の記載を発見したので無事passwordカラムが追加されていそう。 -
rails consoleをでusersテーブルのidが1のユーザのpasswordが登録できるか試してみた。(エラーコードは出なかったためrails console内での出力は省略)
$ 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
-
値をデータベースに保存する時にtrueが出たためpasswordカラムが作成され、正常に値も格納されたことを確認できた。
-
今回の件にはあまり関係無いが、
アプリ名/app/models/user.rb
にpasswordカラムの空欄を弾く様にバリデーションを追記した。下記にuser.rbの内容を記載する。class User < ApplicationRecord validates :email, {presence: true, uniqueness: true} validates :name, {presence: true} validates :password, {presence: true} end