Rails ユーザー認証機能(devise)
deviseというGemを使用したユーザー認証機能の作成方法
ユーザー認証とは
アプリケーションにおいて、操作している人を特定したり、操作できる人を制限する機能のことです。
*InstagramやTwitterなどよく使用するアプリでもアカウントの登録やログイン、ログアウトなどをイメージしてもらうとわかりやすいと思います。
Gemとは
Gemとは他の誰かがすでに作ったコードの塊のことです。
Gemを使うことで、画像加工やフォロー機能、ユーザー認証機能など数多くのコードがあります。
deviseとは
ユーザー認証機能を作成できるGemのことです。
Gemを導入する方法
- Railsアプリケーション内の
Gemfile
に導入したいGemを記載する。
gem 'devise'
- 記載したGemをインストールするために、
bundle install
コマンドを実行する。
$ bundle install
- deviseのインストールを行う。
deviseはGemをインストールした後に、改めてdeviseを動作させるために、
改めてインストールを行う手順が必要です。
$ rails g devise:install
以下のように表示されたらdeviseの設定ファイルが作成されているので成功です。
#省略
create config/initializers/devise.rb
create config/locales/devise.en.yml
#省略
- deviseを使用するモデルの作成
通常はテーブルを設計する際、ユーザーテーブルの作成→ログインに必要なユーザー情報を記述・保存する必要がありますが、deviseを利用してモデルを作成すると、必要な情報を持ったテーブルを自動で作成してくれます。
$ rails g devise User
上記コマンドを実行すると、deviseで利用する機能が記述されたUseモデルや、
usersテーブル用のマイグレーションファイルが作成されます。
- 必要ならdeviseのユーザーテーブルを変更する。
4.のコマンドで作成されたusersテーブルには、ログインに必要以下のカラムがあらかじめ記述されています。
- メールアドレス
- パスワード
- ログイン回数
- ログイン日時
- パスワードを忘れてしまった際のリカバリ
これ以外に必要なカラムがある場合は、自身でカラムを追加する必要があります。
#省略
t.string :name
#省略
- データベースにマイグレーションを行う。
migrateファイルに、必要なカラムを追加できたら、rails db:migrate
でマイグレーションを行います。
$ rails db:migrate
- Routingの確認
deviseのモデルを作成した際に、config/routes.rbには、ルーティングが自動的に追加されていると思うので、確認しておきましょう。
Rails.application.routes.draw do
devise_for :users
root to: 'homes#top'
end
- Viewの確認
ここまででViewやControllerの作成はしてませんが、deviseをインストールして、
モデルを作成しただけでユーザー登録ページやログインページは作成されています。
/users/sign_upや、/users/sign_inにアクセスして試してみましょう。
このようにデフォルトのログイン画面などが作成されていますが、
私が作りたいアプリケーションでは、ログイン時にEmailではなく、nameを使用したいため、
Viewファイルを作成して以下の変更する必要があります。
- ユーザー登録画面:nameの入力欄を追加する
- ログイン画面:emailの入力欄をnameの入力欄に変更する
- Viewファイルの作成・変更
上で確認したデフォルトのViewは、deviseの機能を使ってViewファイルを作成することで、
上書きすることができます。
- Viewファイルの作成
$ rails g devise:views
- ユーザー登録画面の編集
ユーザー名(name)の入力欄を追加する。
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
+ <div class="field">
+ <%= f.label :name %><br>
+ <%= f.text_field :name %>
+ </div>
<div class="field">
<%= f.label :email %><br />
#省略
- ログイン画面の編集
emailを入力する欄を削除し、nameを入力する欄を追加する。
- <%= f.label :email %><br />
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+ <%= f.label :name %><br />
+ <%= f.text_field :name, autofocus: true, autocomplete: "email" %>
以下のようにログインページのemailの入力欄をnameの入力欄に変更することができました。
ユーザー登録ページにもnameの入力欄が作成されています。
- devise初期設定ファイルの修正
認証キーの#コメントアウトを外し、email→nameに変更します。
+ config.authentication_keys = [:name]
- # config.authentication_keys = [:email]
- バリデーションの設定
ユーザー名が空でなく、かつ2文字以上の名前を要求するように設定します。
validates :name, presence:true, length: { minimum: 2 }
- Controllerの変更
deviseは、ユーザー登録・ログイン時に「email」と「password」しか保存することが許可されていないため、nameなど指定したデータを保存できるように許可を与える必要があります。
*特定のデータを保存できるように許可を与えるためには、ストロングパラメータを編集します。
以下のように記述します。
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
end
-
before_action :configure_permitted_parameters, if: :devise_controller?
deviseの機能(ユーザー登録・ログイン認証)などが行われる前に、configure_permitted_parametersメソッドが実行されます。 -
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
ユーザー登録の際に、ユーザー名(name)のデータ操作を許可しています。 -
protected
privateは記述したコントローラ内でしか参照されませんが、protectedは呼び出された他のコントローラからも参照することがきます。
- ログアウトリンクの作成
10.までで、ログインやユーザー登録はできるようになりましたが、ログアウト機能を実装しなければなりません。
deviseの初期機能でログアウト機能自体は作られているので、ログアウトのリンクを作ります。
- 今回はログイン状態ならログアウトリンクを表示、ログアウト状態ならログイン・新規登録リンクを表示します。
<body>
<header>
+ <% if user_signed_in? %>
+ <li>
+ <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
+ </li>
+ <% else %>
+ <li>
+ <%= link_to "新規登録", new_user_registration_path %>
+ </li>
+ <li>
+ <%= link_to "ログイン", new_user_session_path %>
+ </li>
+ <% end %>
<%= yield %>
</body>
- deviseのフォームヘルパーを変更する
deviseで作成されるViewでは、入力フォームを表示するヘルパーとしてform_for
が使用されています。
現在form_forは非推奨なので、form_with
に変更する必要があります。
<h2>Sign up</h2>
- <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
+ <%= form_with model: @user, url: user_registration_path do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
:
<h2>Log in</h2>
- <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
+ <%= form_with model: @user, url: user_session_path do |f| %>
<div class="field">
- 完成
これでdeviseを使ったユーザー認証機能が完成しました。
Discussion