【Rails】ゲストログイン・簡単ログイン機能の実装
はじめに
ポートフォリオ用のWebサイトに必須と言われるゲストログイン機能。
特にDeviseのconfirmableを使用している場合は,ゲストログイン機能が無いと,新規登録が面倒という理由でポートフォリオを見てすらもらえない可能性が高くなります。
ところが,普通のWebサイトには導入しないためか,良い記事が見当たりませんでした。
今回は上記の記事を参考にしていきます。
以下,Deviseを使用している前提とします。
ゲストログイン機能の実装方法
上記の記事の方法ではゲスト機能を、ホームコントローラーを使用しているので新しくコントローラーを作成するのが良いと思います。
ターミナル
rails g controller guests
私は今回のポートフォリオで管理者側と顧客側で分かれていた為、
rails g controller public/guests と rails g controller admin/guests
で作成しています。
config/routes.rb
# 以下を追加
post '/guests/guest_sign_in', to: 'guests#new_guest'
app/controllers/guests_controller.rb
# 以下を追加
def new_guest
user = User.find_or_create_by!(email: 'guest@example.com') do |user|
user.password = SecureRandom.urlsafe_base64
# user.confirmed_at = Time.now # Confirmable を使用している場合は必要
end
sign_in user
redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。'
end
userの変数はcustomerなどに変える事ができます。
emailとパスワードの他にユーザー情報を持っている場合は、emailの後にデータを入れてください。(バリデーションがかかっていなければなくてもOKですが)
app/views/layout/application.html.erb
# 以下を追加
完成!ログインが出来るか確かめてください。
<%= link_to 'ゲストログイン(閲覧用)', guests_guest_sign_in_path, method: :post %>
ポイントはDeviseのsign_inメソッドを利用することです。
find_byではなく,find_or_create_byを利用しています。これにより,ゲストユーザーをあらかじめ作成する手間を省けます。また,ゲストユーザーを削除されてゲスト機能が動作しなくなるリスクも回避できます。
パスワードを特定されると,ユーザー編集ページからメールアドレス・パスワードを変更される可能性があるため,パスワードはランダム文字列にしています。
バリデーションの影響でゲストユーザーを作成できない場合は,エラーを発生させるように設定しております。
ゲストユーザーが削除機能を使用できないようにするには,registrations.rbを編集する必要があります。まずは,ルーティングを変更します。
config/routes.rb
# devise_for :users を次に置き換える
devise_for :users, controllers: {
registrations: 'users/registrations'
}
destroyアクションの動作前に,メールアドレスがゲストユーザー用になっていないかチェックするように設定します。
ゲストユーザーならばフラッシュを出した上でトップページにリダイレクトさせるように設定しています。
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
before_action :check_guest, only: :destroy
def check_guest
if resource.email == 'guest@example.com'
redirect_to root_path, alert: 'ゲストユーザーは削除できません。'
end
end
end
2-3 ゲストユーザーがメールアドレス・パスワードを変更できないようにする
上記の実装ならば,「ユーザー編集機能」や「パスワード再設定機能」によりメールアドレス・パスワードを変更される可能性は非常に低いですし,仮に変更されたとしてもポートフォリオならば問題にならないかと思います。
それでも,「ゲストユーザーのメールアドレス・パスワードを絶対に変更されたくない!」という場合は,更に次のような設定をすればOKです。
削除機能を止めるのと同じ手法で,ゲストユーザーがメールアドレス・パスワードを編集できないように設定します。
app/controllers/users/registrations_controller.rb
- before_action :check_guest, only: :destroy
+ before_action :check_guest, only: %i[update destroy]
- redirect_to root_path, alert: 'ゲストユーザーは削除できません。'
+ redirect_to root_path, alert: 'ゲストユーザーの変更・削除はできません。'
パスワード再設定メールの送信機能を止めるには,passwords_controller.rbのcreateアクションの動作前にチェックすればOKです。まずはルーティングを変更します。
config/routes.rb
# devise_for :users, controllers: {
# registrations: 'users/registrations'
# }
# を次に置き換える。(,の付け忘れに注意!)
devise_for :users, controllers: {
registrations: 'users/registrations',
passwords: 'users/passwords'
}
パスワード再設定ページのフォームに入力されたメールアドレスはparams[:user][:email]で受け取れるので,これを利用してゲストユーザーを特定します。
メールアドレスは大文字が小文字に変換されて保存されているため,downcaseメソッドが必要です。
app/controllers/users/passwords_controller.rb
class Users::PasswordsController < Devise::PasswordsController
before_action :check_guest, only: :create
def check_guest
if params[:user][:email].downcase == 'guest@example.com'
redirect_to root_path, alert: 'ゲストユーザーの変更・削除はできません。'
end
end
end
【補足】 check_guestがほぼ同じ内容ですので,次のようにまとめてしまってもOKです。
app/controllers/application_controller.rb
# 次を追加
# registrations_controller.rb と passwords_controller.rb の check_guest は削除
def check_guest
email = resource&.email || params[:user][:email].downcase
if email == 'guest@example.com'
redirect_to root_path, alert: 'ゲストユーザーの変更・削除はできません。'
end
end
備考
上記はあくまで最低限度の実装です。例えば,ゲストユーザーの情報は他の利用者にも引き継がれますので,必要があればTrackableを入れて,current_sign_in_atを基準に次のような実装をしてもよいかもしれません。
定期的にデータを初期化する設定を入れる
ゲストユーザーを複数用意して,現在ログイン日時の最も古いゲストユーザーでログインする
実は,最初,devise/sessions/new.html.erbの真似をして,hidden_fieldを加えて……という手順で実装しようとしました。ところが,この方法ではuser_email, user_passwordなどのidセレクタが重複するエラーが出てしまいます。そこで,sign_inメソッドの存在を思い出し,このような実装方法にたどりつきました。
この記事が気に入ったらサポートをしてみませんか?