前回(第1回)では、DockerとTablerを使ったRails開発環境に、定番の認証GemであるDeviseをインストールし、初期設定、Userモデルの作成、そして認証関連のURL(/admin/sign_in
など)を/admin
配下に設定しました。Deviseを動かすための土台はできましたが、まだユーザーが実際にログインしたり、アカウントを作成したりすることはできませんでした。
この第2回では、いよいよ実際にユーザー認証機能を「使える」状態にします!具体的には以下の内容を進めます。
devise_for
によって生成されたルーティングを確認します。- ユーザーがアカウントを新規登録(サインアップ)できることを確認します。
- 登録したアカウントでログイン(サインイン)、そしてログアウト(サインアウト)できることを確認します。
- Deviseが提供する便利なヘルパーメソッドを使い、ログイン状態に応じて表示を変えたり、アクセス制御をしたりする方法を学びます。
この記事を読み終えれば、あなたのアプリケーションでDeviseによる基本的な認証フローが一通り動作し、その仕組みを理解できるはずです。
前提となる開発環境
この記事は、以下の環境が整っていることを前提としています。
- DockerおよびDocker Compose
-
アプリケーションとデータベースなどがコンテナ管理されている。
- Tablerレイアウト
-
Tabler UIキット が導入済みで、
app/views/layouts/admin.html.erb
等の管理画面用レイアウトがある。 - Devise導入済み
-
第1回の内容に従い、Devise Gemがインストールされ、初期設定、Userモデル生成、DBマイグレーションが完了し、認証URLが
/admin
配下に設定されている。 - Flashメッセージ表示
-
レイアウトに
<%= render "shared/flash_messages" %>
が設置されている。
Step 1: Deviseルーティングの確認
まず、第1回で config/routes.rb
に設定した devise_for
が、実際にどのようなURLパスを生成しているか確認しましょう。Railsコンテナ内で以下のコマンドを実行します。
# devise に関連するルーティングを表示
bin/rails routes | grep devise
出力結果の中に、以下のような /admin
から始まるパスが含まれているはずです(scope '/admin'
と path: ''
, path_names
の設定に基づきます)。
new_user_session GET /admin/sign_in(.:format) # ログインフォーム表示
user_session POST /admin/sign_in(.:format) # ログイン処理
destroy_user_session DELETE /admin/sign_out(.:format) # ログアウト処理
user_password POST /admin/password(.:format) # パスワードリセットメール送信
new_user_password GET /admin/password/new(.:format) # パスワードリセット要求フォーム
edit_user_password GET /admin/password/edit(.:format) # パスワード再設定フォーム
user_password PATCH /admin/password(.:format) # パスワード更新処理
PUT /admin/password(.:format) # パスワード更新処理
POST /admin/password(.:format) # パスワードリセットメール送信
cancel_user_registration GET /admin/cancel(.:format) # サインアップキャンセル
new_user_registration GET /admin/sign_up(.:format) # サインアップフォーム表示
edit_user_registration GET /admin/edit(.:format) # アカウント編集フォーム表示
user_registration PATCH /admin(.:format) # アカウント更新処理
PUT /admin(.:format) # アカウント更新処理
DELETE /admin(.:format) # アカウント削除処理
POST /admin(.:format) # サインアップ処理
これらのパスを使って、実際に認証機能を試していきます。
Step 2: サインアップ機能の実装と確認
ユーザーが自身のアカウントを作成できるようにします。
- 1. 開発サーバーを起動(まだ起動していない場合)
-
bash docker compose up -d
- 2. サインアップページへアクセス
-
- 表示内容
-
Deviseのデフォルトのサインアップフォーム(Email, Password, Password confirmation入力欄)が表示されます。
- 注意
-
第1回の最後で触れた通り、この時点では管理画面のTablerレイアウトは適用されていません。これは、Deviseのコントローラーがデフォルトのレイアウトを使用するためです。レイアウト適用とフォームのカスタマイズは次回の記事で行います。
- アカウント作成
-
フォームに有効なメールアドレスと、パスワード(確認用も同じもの)を入力して送信ボタンをクリックします。
- 結果確認
-
成功すればリダイレクト、失敗すればエラーメッセージが表示されます。
- 結果確認
-
- 成功時
-
デフォルトではアプリケーションのルートパス (
root_path
で設定したパス) にリダイレクトされ、「アカウント登録が完了しました。」(Welcome! You have signed up successfully.) のようなnotice
Flashメッセージが表示されるはずです。 - 失敗時
-
パスワードが短い、確認用パスワードが違う、Email形式が不正などのバリデーションエラーがあれば、フォームページが再表示され、エラー内容を示す
alert
Flashメッセージが表示されます。(これは:validatable
モジュールによるものです)
- DB確認 (任意)
-
Railsコンソール (
bin/rails c
) でUser.count
やUser.last
を実行し、ユーザーがデータベースに正しく保存されたことを確認できます。
これで、ユーザー登録機能が動作することが確認できました。
Step 3: ログイン (サインイン) と ログアウト (サインアウト) を試す
次に、登録したアカウントでログインし、その後ログアウトできるかを確認します。
- 1. サインインページへアクセス
-
ブラウザで
http://localhost:3000/admin/sign_in
にアクセスします。デフォルトのサインインフォームが表示されます - 2. ログイン試行
-
- 成功
-
Step 2で登録したメールアドレスとパスワードを入力し、送信します。
成功すると、デフォルトでルートパスにリダイレクトされ、「ログインしました。」(Signed in successfully.) のnotice
Flashメッセージが表示されます。 - 失敗
-
情報が間違っている場合、サインインページが再表示され、「メールアドレスまたはパスワードが違います。」(Invalid Email or password.) の
alert
Flashメッセージが表示されます。 - ログイン済みの場合の挙動
-
もし、既にログインしている状態(例えば、サインアップ直後など)で
/admin/sign_in
にアクセスしようとすると、Devise は自動的にルートパスなどにリダイレクトし、“You are already signed in.” (すでにログインしています。) というalert
Flashメッセージを表示します。
これはエラーではなく、Devise の正常な動作であり、二重ログインを防ぐための挙動です。
サインイン機能を試す際は、一度ログアウトしてからアクセスするか、シークレットモード/プライベートブラウジングのウィンドウで試すと良いでしょう。
- 3. サインアウト用リンク/ボタンの設置
-
ログアウト機能を使うには、ログアウト処理を行うパス (
/admin/sign_out
) へ DELETEメソッドでリクエストを送る必要があります。
管理画面共通ヘッダー (app/views/shared/_header.html.erb
) などにリンクまたはボタンを設置します。<header class="navbar navbar-expand-md d-print-none"> <div class="container-xl"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu" aria-controls="sidebar-menu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <h1 class="navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0 pe-md-3"> <%= link_to admin_root_path, class: "navbar-brand" do %> MyApp <% end %> </h1> <div class="navbar-nav flex-row order-md-last"> <div class="nav-item"> <%= button_to "ログアウト", destroy_user_session_path, method: :delete, class: "nav-link", form: { class: 'd-inline' } %> </div> </div> </div> </header>
destroy_user_session_path
は/admin/sign_out
へのルーティングヘルパーです。- 重要:
button_to
にmethod: :delete
を指定するか、link_to
にdata: { turbo_method: :delete }
を指定しないと、GETリクエストになってしまい正しくログアウトできません。
- 4. ログアウト実行
-
ログインした状態で、設置したログアウトリンク/ボタンをクリックします。
- 5. 結果確認
-
成功すると、デフォルトでルートパスにリダイレクトされ、「ログアウトしました。」(Signed out successfully.) の
notice
Flashメッセージが表示されます。
これで、ログインとログアウトの基本的なフローも動作することが確認できました。
Step 4: Deviseヘルパーで認証状態を活用する
Deviseは、ビューやコントローラーで認証状態を簡単に扱えるように、いくつかの便利なヘルパーメソッドを提供します。これらを使ってアプリケーションをより機能的にしましょう。
authenticate_user!
: コントローラーでのアクセス制御
これはコントローラー内 (主に before_action
として) で使用し、ログインしていないユーザーからのアクセスを拒否(ログインページへリダイレクト)するためのメソッドです。管理画面全体など、特定のエリアをログイン必須にしたい場合に非常に役立ちます。
- 実装例: 管理画面全体をログイン必須にする
-
# app/controllers/admin/base_controller.rb class Admin::BaseController < ApplicationController layout 'admin' before_action :authenticate_user! end
この1行を追加するだけで、
/admin
配下の(Admin::BaseController
を継承している)全てのページは、ログインしていないユーザーがアクセスしようとすると自動的にログインページ (/admin/sign_in
) へリダイレクトされるようになります。
user_signed_in?
と current_user
: ビューでの表示切り替えとユーザー情報表示
- user_signed_in?
-
ユーザーが現在ログインしているかどうかを
true
/false
で返します。ビューファイル内で条件分岐によく使われます。 - current_user
-
現在ログインしているユーザーの
User
モデルオブジェクトを返します。ログインしていない場合はnil
を返します。ユーザーの名前やメールアドレスなどを表示するのに使います。 - 実装例: 管理画面ヘッダーのナビゲーションを完成させる
-
<%# app/views/layouts/admin.html.erb のヘッダー部分の例 %> <header class="navbar navbar-expand-md d-print-none"> <div class="container-xl"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu" aria-controls="sidebar-menu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <h1 class="navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0 pe-md-3"> <%= link_to admin_root_path, class: "navbar-brand" do %> MyApp <% end %> </h1> <div class="navbar-nav flex-row order-md-last"> <% if user_signed_in? %> <%# --- ログインしている場合の表示 --- %> <div class="nav-item dropdown"> <a href="#" class="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown" aria-label="Open user menu"> <div class="d-none d-xl-block ps-2"> <%# current_user を使ってメールアドレス表示 %> <div><%= current_user.email %></div> <div class="mt-1 small text-muted">ログイン中</div> </div> </a> <%# ドロップダウンメニュー %> <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"> <%= link_to "アカウント設定", edit_user_registration_path, class: "dropdown-item" %> <%# /admin/account %> <div class="dropdown-divider"></div> <%= button_to "ログアウト", destroy_user_session_path, method: :delete, class: "dropdown-item" %> </div> </div> <% end %> </div> </div> </header>
if user_signed_in?
でログイン状態をチェックし、表示判定をしています。- ログイン中は
current_user.email
でメールアドレスを取得して表示しています。
これらのヘルパーを使うことで、認証状態に基づいた動的なページを簡単に構築できます。
まとめと次回予告
第2回では、Devise を使ったアプリケーションで、ユーザーが実際にサインアップ、サインイン、サインアウトできることを確認しました。また、Devise が提供する user_signed_in?
, current_user
, authenticate_user!
といった基本的なヘルパーメソッドを使い、ビューの表示を切り替えたり、コントローラーでアクセス制御を行ったりする具体的な方法を学びました。
これで、あなたの Rails アプリケーションは動作する認証機能の基盤を持つことになりました。しかし、現状では Devise の認証画面はデフォルトのままで、管理画面のレイアウトも適用されていません。
次回(第3回) は、この認証画面の見た目を改善します。具体的には、Devise の認証画面(サインイン、サインアップ等)に管理画面の Tabler レイアウト (admin.html.erb
) を適用する方法と、rails g devise:views
コマンドで生成したビューファイルを編集してフォーム等の見た目を Tabler デザインにカスタマイズする手順を詳しく解説します。より洗練された認証画面を目指しましょう!