🗝️

Rails ユーザー認証機能(devise)

2023/08/12に公開

deviseというGemを使用したユーザー認証機能の作成方法

ユーザー認証とは

アプリケーションにおいて、操作している人を特定したり、操作できる人を制限する機能のことです。
*InstagramやTwitterなどよく使用するアプリでもアカウントの登録やログイン、ログアウトなどをイメージしてもらうとわかりやすいと思います。

Gemとは

Gemとは他の誰かがすでに作ったコードの塊のことです。
Gemを使うことで、画像加工やフォロー機能、ユーザー認証機能など数多くのコードがあります。

deviseとは

ユーザー認証機能を作成できるGemのことです。
https://github.com/heartcombo/devise

Gemを導入する方法

  1. Railsアプリケーション内のGemfileに導入したいGemを記載する。
Gemfile
gem 'devise'
  1. 記載したGemをインストールするために、bundle installコマンドを実行する。
ターミナル
$ bundle install
  1. deviseのインストールを行う。

deviseはGemをインストールした後に、改めてdeviseを動作させるために、
改めてインストールを行う手順が必要です。

ターミナル
$ rails g devise:install

以下のように表示されたらdeviseの設定ファイルが作成されているので成功です。

ターミナル
#省略
create  config/initializers/devise.rb
create  config/locales/devise.en.yml
#省略
  1. deviseを使用するモデルの作成

通常はテーブルを設計する際、ユーザーテーブルの作成→ログインに必要なユーザー情報を記述・保存する必要がありますが、deviseを利用してモデルを作成すると、必要な情報を持ったテーブルを自動で作成してくれます。

ターミナル
$ rails g devise User

上記コマンドを実行すると、deviseで利用する機能が記述されたUseモデルや、
usersテーブル用のマイグレーションファイルが作成されます。

  1. 必要ならdeviseのユーザーテーブルを変更する。

4.のコマンドで作成されたusersテーブルには、ログインに必要以下のカラムがあらかじめ記述されています。

  • メールアドレス
  • パスワード
  • ログイン回数
  • ログイン日時
  • パスワードを忘れてしまった際のリカバリ
    これ以外に必要なカラムがある場合は、自身でカラムを追加する必要があります。
db/migrate/(作成日時)_devise_criate_users.rb
#省略
t.string :name
#省略
  1. データベースにマイグレーションを行う。

migrateファイルに、必要なカラムを追加できたら、rails db:migrateでマイグレーションを行います。

ターミナル
$ rails db:migrate
  1. Routingの確認

deviseのモデルを作成した際に、config/routes.rbには、ルーティングが自動的に追加されていると思うので、確認しておきましょう。

config/routes.rb
Rails.application.routes.draw do
devise_for :users
root to: 'homes#top'
end
  1. Viewの確認

ここまででViewやControllerの作成はしてませんが、deviseをインストールして、
モデルを作成しただけでユーザー登録ページやログインページは作成されています。
/users/sign_upや、/users/sign_inにアクセスして試してみましょう。

このようにデフォルトのログイン画面などが作成されていますが、
私が作りたいアプリケーションでは、ログイン時にEmailではなく、nameを使用したいため、
Viewファイルを作成して以下の変更する必要があります。

  • ユーザー登録画面:nameの入力欄を追加する
  • ログイン画面:emailの入力欄をnameの入力欄に変更する
  1. Viewファイルの作成・変更
    上で確認したデフォルトのViewは、deviseの機能を使ってViewファイルを作成することで、
    上書きすることができます。
  • Viewファイルの作成
ターミナル
$ rails g devise:views
  • ユーザー登録画面の編集
    ユーザー名(name)の入力欄を追加する。
app/views/devise/registrations/new.html.erb

 <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を入力する欄を追加する。
app/views/devise/sessions/new.html.erb
-  <%= 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/initializers/devise.rb
+ config.authentication_keys = [:name]
- # config.authentication_keys = [:email]
  • バリデーションの設定

ユーザー名が空でなく、かつ2文字以上の名前を要求するように設定します。

app/models/user.rb
validates :name, presence:true, length: { minimum: 2 }
  1. Controllerの変更

deviseは、ユーザー登録・ログイン時に「email」と「password」しか保存することが許可されていないため、nameなど指定したデータを保存できるように許可を与える必要があります。
*特定のデータを保存できるように許可を与えるためには、ストロングパラメータを編集します。

以下のように記述します。

app/controllers/applicattion_controller.rb
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は呼び出された他のコントローラからも参照することがきます。
  1. ログアウトリンクの作成

10.までで、ログインやユーザー登録はできるようになりましたが、ログアウト機能を実装しなければなりません。
deviseの初期機能でログアウト機能自体は作られているので、ログアウトのリンクを作ります。

  • 今回はログイン状態ならログアウトリンクを表示、ログアウト状態ならログイン・新規登録リンクを表示します。
app/views/layouts/application.html.erb
  <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>
  1. deviseのフォームヘルパーを変更する

deviseで作成されるViewでは、入力フォームを表示するヘルパーとしてform_forが使用されています。
現在form_forは非推奨なので、form_withに変更する必要があります。

app/views/devise/registrations/new.html.erb
 <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 %>
  :
app/views/devise/sessions/new.html.erb
 <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">
  1. 完成

これでdeviseを使ったユーザー認証機能が完成しました。

Discussion