Rails7でポートフォリオ用のWebサイト(もしくは正式なWebサービス)にゲストログイン機能を実装したい。
ネットでググるとDeviseでゲストログイン機能を実装する方法はたくさん出てきますが、「Rails7」+「Devise」と言う条件下でゲストログイン機能を実装する方法はあまり見かけない。
現時点(2022年10月)ではまだDeviseがRails7(Turbo)に対応していないため、「Rails7」+「Devise」でゲストログインを実装するためにはコントローラーのカスタマイズが必要です。
そこで、当記事では「Rails7」+「Devise」と言う条件下でゲストログイン機能を実装する方法についてまとめました。
開発環境
- Ruby 3.1.2
- Ruby on Rails 7.0.4
- Devise 4.8.1
- M1 Macbook Air 2020
- mac OS Monterey (ver. 12.4)
- ターミナル bash (Rosetta 2 使用)
Rails7にDeviseを導入する
まずはRails7にDeviseを導入します。
Rails7にDeviseを導入する方法は以下の記事にまとめてあるので参考にしながら実装してみてください。
Rails7へDeviseの実装が終わったら、次へ進みます。
Deviseでゲストログイン機能を実装する流れ
ゲストログイン機能を実装する大まかな流れです。
- Sessionsコントローラーにゲストログイン用のアクション
guest_sign_in
を追加 - ルーティング設定
- ゲストログイン用のリンク(ボタン)を設置
それでは順に進めていきます。
Sessionsコントローラー設定
Deviseはデフォルトで内部のコントローラーを参照しているため、gemをインストールした時点ではアプリケーション内にコントローラーがありません。
独自にコントローラーの内容を設定(デフォルトの設定を変更、オーバーライド)するためには各自カスタム用のコントローラーを追加、および後ほどルーティングの設定を行う必要があります。
Rails7にDeviseを導入する時点(こちらの記事)ですでにカスタム用コントローラーapp/controllers/users/sessions_controller.rb
を追加しているかと思うので、
作成済みのapp/controllers/users/sessions_controller.rb
に以下の内容を記述します。
class Users::SessionsController < Devise::SessionsController
def guest_sign_in
user = User.find_or_create_by(email: "guest@example.com") do |user|
user.password = SecureRandom.urlsafe_base64
user.confirmed_at = Time.now # ← Confirmable を設定している場合は追加
# user.name = "ゲストユーザー" # ←ユーザー名を設定している場合は追加
end
sign_in user # ← Deviseのログインメソッド
redirect_to root_path, notice: "ゲストユーザーとしてログインしました"
end
# ・・・ (Rails7へDviseを導入する際に追記した内容) ・・・
end
もし追加していない場合は、app/controllers
以下にusers
フォルダを作成し、users
内にsessions_controller.rb
を新規作成してから上記の内容を追加します。
また、以下のようにゲストアカウントを生成・検索する部分をuserモデルにメソッド化しておくと、Sessionsコントローラーがスッキリするかと思います。
class Users::SessionsController < Devise::SessionsController
def guest_sign_in
user = User.guest # ← user.rbで定義したメソッド
sign_in user
redirect_to root_path, notice: "ゲストユーザーとしてログインしました"
end
# ・・・ (Rails7へDviseを導入する際に追記した内容) ・・・
end
class User < ApplicationRecord
・・・
# 下記メソッドを追加
def self.guest
find_or_create_by!(email: "guest@example.com") do |user|
user.password = SecureRandom.urlsafe_base64
user.confirmed_at = Time.now # ← Confirmable を設定している場合は追加
# user.name = "ゲストユーザー" # ←ユーザー名を設定している場合は追加
end
end
end
ルーティング設定
Sessionsコントローラーの設定が反映されるようにするため、config/routes.rb
に以下のように記述します。
devise_scope :user do
post "users/guest_sign_in", to: "users/sessions#guest_sign_in"
end
ゲストログインリンク(ボタン)の設置
ゲストログイン用のリンクをトップページなどに設置します。
= link_to "ゲストログイン", users_guest_sign_in_path, data: { turbo_method: :post }
一応、これでゲストログイン機能が動くようになりました。
ただ、現時点だとゲストユーザーの編集・削除ができてしまうため、もしゲストユーザーに複数のログインがあった場合、誰かがゲストアカウントを削除すると他のユーザーは強制的にログアウトさせられます。
(まぁ、ポートフォリオサイトでそういうことは滅多にないと思いますが)
そこで、ゲストユーザーの編集・削除ができないよう対策する必要があります。
ゲストユーザーの編集・削除ができないようにする
これから行う設定により、ゲストユーザーの編集・削除、およびパスワードの変更ができないようになります。
「ゲストユーザーのメールアドレス・パスワードを絶対に変更されたくない!」と言う方は設定を進めてください。
まずは、config/routes.rb
に以下のように記述します。
(Rails7でDeviseを導入した場合は、すでにregistrations:
が記述されていると思うので、passwords:
の行のみ追記します)
# devise_for :users を次の内容に置き換える
devise_for :users, controllers: {
registrations: 'users/registrations',
passwords: 'users/passwords'
}
app/controllers/users/registrations_controller.rb
、およびapp/controllers/users/passwords_controller.rb
を新規作成し、それぞれ以下の内容を追記します。
(すでに作成済みの場合はファイルを開いて以下の内容を追記)
class Users::RegistrationsController < Devise::RegistrationsController
before_action :ensure_general_user, only: [:update, :destroy]
def ensure_general_user
if resource.email == "guest@example.com"
redirect_to root_path, alert: "ゲストユーザーの変更・削除はできません"
end
end
# ・・・ (Rails7へDviseを導入する際に追記した内容) ・・・
end
class Users::PasswordsController < Devise::PasswordsController
before_action :ensure_general_user, only: :create
def ensure_general_user
if params[:user][:email].downcase == "guest@example.com" # パスワード再設定ページのフォームに入力されたメールアドレスはparams[:user][:email]で受け取れる
redirect_to new_user_session_path, alert: "ゲストユーザーのパスワード再設定はできません"
end
end
end
これでゲストユーザーの編集・削除、およびパスワードの変更ができないようになるはずです。
以上です。
コメント