【UnknownAttributeError】テーブルの修正方法【Rails】

createアクションで実際に発生したエラー

どうも、てーやまです。

実際にWebアプリを開発していく中で起きたエラーと、その解消方法を残していこうと思います。

そんな中でも今回は、『Railsのモデル定義(DB設計)に誤った時の修正方法』を記載したいと思います。

UnknownAttributeErrorが発生

やりたかったこと

ユーザーIDの新規登録画面でよく見かける『パスワードの再入力フォーム』を作成しました。

CSSが一切あたっていないビューなので見辛いですが、すみません。。

ユーザーIDを新規登録する場合、パスワードの入力は必須のケースが多いですが、確認用にもう一度同じパスワードを入力してくださいという、アレです。

僕がやりたかったのは、以下の2つです。
①パスワードとパスワード(確認)が不一致であればエラーとする
②パスワードをDBに保存する

今日はそのうちの『②パスワードをDBに保存する』の際に『UnknownAttributeError』が発生しました。

UnknownAttributeErrorとは

UnknownAttributeError

unknown attribute ‘password_confirmation’ for User.と書かれています。
Userモデルに’password_confirmation’なんて属性は存在しませんと言っています。ちなみにその際のコントローラは以下のようになっています。

def create
		user = User.new(user_params)
		if user.save
			redirect_to studies_path
		else
			redirect_to :back
		end
	end

	private

	def user_params
		params.require(:user).permit(:name, :password, :password_confirmation, :emailaddress)
	end

上記では新規登録画面から渡ってきた『password_confirmation』(即ちパスワード(確認)のことです)を受け取り、『password』と比較した後、usersテーブルに保存を試みています。

しかし、usersテーブルにはそんなカラムは存在しないから保存できないよと怒られているわけですね。

confirmationとDB再設計

まず『confirmation』はRailsのバリデーションヘルパーの一種であり、バリデーションとは、オブジェクトをDBに保存する前にその状態を検証できる機能です。

『confirmation』を使うと先のパスワードとパスワード(確認用)のように、2つのフィールドで受け取る内容が一致しているかを検証することができます。

またDBにおける『暗号化されたパスワード領域』は『password_digest』というカラムを追加することで保存できます。

テーブルにカラムを追加する手順

それではテーブル更新を行なっていきます。

マイグレーションファイルを作成する

Usersテーブルに新たに『password_digest』カラムを追加するマイグレーションファイルを作成します。

$ docker-compose run web rails g migration AddPasswordDigestToUsers password_digest:string
class AddPasswordDigestToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :password_digest, :string
  end
end

後はマイグレーションを実行します。

$ docker-compose run web rails db:migrate

その後にテーブル定義を確認してみると、『password_digest』が追加されています。

$ docker-compose exec web bash
# rails dbconsole
# \d users
     Column      |            Type             | Collation | Nullable |              Default              
-----------------+-----------------------------+-----------+----------+-----------------------------------
 id              | integer                     |           | not null | nextval('users_id_seq'::regclass)
 name            | character varying           |           |          | 
 mailaddress     | character varying           |           |          | 
 created_at      | timestamp without time zone |           | not null | 
 updated_at      | timestamp without time zone |           | not null | 
 password_digest | character varying           |           |          | 
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)

これで『UnknownAttributeError』が解消し、暗号化されたパスワードが保存できるようになりました。