ゲストログイン機能の実装
ゲストログイン機能の実装
今回は以前作成したアプリケーションにゲストログイン機能を実装していく。
使用するアプリケーション 参考URL 作成するアプリケーションについて - takifugu’s blog
前提条件
GemのDeviseを使用(導入済み)
仕様
トップページにゲストログインボタンを配置する。
ゲストログインボタンを押すと、ゲストユーザーでログイン状態となり、ユーザー詳細画面に遷移する。
ゲストユーザーのnameとemailは事前に作成しておく。
ゲストユーザーはユーザー編集機能を使用できないようにする。(ユーザー編集ボタンの削除、アクセス制限の実装)
実装手順
ゲストログインメソッドの作成
ルーティングの記述
ゲストメソッドの定義
ゲストログインボタンの作成
ゲストログイン時、ユーザ編集ボタンの非表示
ゲストユーザーのユーザー編集へのアクセス制限の実装
ゲストログイン機能の実装
ゲストログインメソッドの作成
Deviseではsign_inというメソッドが存在しており、これはユーザーをログイン状態にするものです。
通常のログイン機能はsessions_controller.rbに記述されており、Gemでインストールされているため、
ディレクトリツリーからは確認できません。
今回は、ゲストログイン用に独自のメソッドを作成するため、sessions_controllerの機能を継承して実装していきます。
app/controllersの配下にusersフォルダを作成し、フォルダ内にsessions_controller.rbを作成し、記述していきます。
app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController def guest_sign_in user = User.guest sign_in user redirect_to user_path(user), notice: "guestuserでログインしました。" end end
ここでゲストユーザーのログインメソッドを記述しています。
Users::SessionsController < Devise::SessionsControllerでDeviseのsessions_controllerを継承するという記述。
guestメソッドは後で作成するため、現状では未定義。
sign_in後にユーザーの詳細画面に遷移し、noticeをフラッシュメッセージとして出します。
ルーティングの記述
作成したsessions_controllerへ処理を行うためのルーティングを設定します。
config/routes.rb
: devise_scope :user do post "users/guest_sign_in", to: "users/sessions#guest_sign_in" end :
devise_scopeでdeviseに新しくルーティングを使用したいときや既存のURLをカスタマイズしたいときに使用する。
この記述を使用しないとエラーが発生する。
ルーティングを確認すると以下のようになっている。
$ rails routes
ゲストメソッドの定義
先程作成したゲストログインメソッドで使用していたguestメソッドを定義していく。
app/models/user.rb
: GUEST_USER_EMAIL = "guest@example.com" def self.guest find_or_create_by!(email: GUEST_USER_EMAIL) do |user| user.password = SecureRandom.urlsafe_base64 user.name = "guestuser" end end :
GUEST_USER_EMAIL = "guest@example.com"でゲストユーザーのemailを定義。
find_or_create_by?(条件)メソッドは、
条件としたデータが存在するかを確認し、存在する場合は、そのデータを返し、存在しない場合は、新規作成する。
また、find_or_create_by!の「!」を付与することで、処理がうまくいかなかった場合にエラーが発生するようになり、結果不具合を検知しやすくなります。
パスワードはSecureRandom.urlsafe_base64でランダムな文字列を生成しています。
nameは"guestuser"として固定しています。
このようにUser.rbに記述することで、Userモデルで使用できるメソッドとしてUser.guestの記述が可能になります。
ゲストログインボタンの作成
top画面にゲストログインボタンを作成します。
app/views/homes/top.html.erb
: <div class="btn-wrapper mx-auto col-10"> #ここから追加 <div class="row"> <%= link_to "ゲストログイン(閲覧用)", users_guest_sign_in_path, class: "btn btn-secondary btn-sm btn-block mb-3 sign_in", method: :post %> </div> #ここまで <div class="row"> <%= link_to "Log in", new_user_session_path, class: "btn btn-sm btn-info btn-block mb-3" %> </div> <div class="row"> <%= link_to "Sign up", new_user_registration_path, class: "btn btn-sm btn-success btn-block" %> </div> </div> :
これでゲストログインできるようになりました。
ここから、ゲストユーザーがユーザー編集できないように設定していきます。
(ユーザー編集できると、編集された後にゲストログインできなくなるため。)
ゲストログイン時、ユーザ編集ボタンの非表示
サイドバーのユーザー編集画面へのリンクボタンをゲストユーザーの時は、非表示にしていきます。
app/views/users/_info.html.erb
: # if文を追加 <% if user.email != "guest@example.com" %> <div class="row"> <%= link_to "",edit_user_path(user),class: "btn btn-outline-secondary btn-block fas fa-user-cog edit_user_#{user.id}" %> </div> <% end %>
これでユーザーのemailがguest@example.comの時は表示しなくなりました。
ゲストユーザーのユーザー編集へのアクセス制限の実装
最後に、ユーザーの編集画面へのURLを直接入力された場合に、メッセージを表示してユーザー詳細画面へリダイレクトする記述をしていきます。
app/controllers/users_controller.rb
class UsersController < ApplicationController before_action :ensure_guest_user, only: [:edit, update] : private : def ensure_guest_user @user = User.find(params[:id]) if @user.email == "guest@example.com" redirect_to user_path(current_user) , notice: "ゲストユーザーはプロフィール編集画面へ遷移できません。" end end end
これでゲストユーザーのログイン機能は実装完了です。
ここから一部コードをブラッシュアップし、汎用性を高く保つようにします。
ゲストユーザーであるかの判別をしている下記の箇所をメソッドを作成し、記述を変更します。
app/views/users/_info.html.erb
<% if user.email != "guest@example.com" %>
app/controllers/users_controller.rb
if @user.email == "guest@example.com"
user.rbにguest_user?というメソッドを作成します。
app/models/user.rb
def guest_user? email == GUEST_USER_EMAIL end
このメソッドでは、emailが以前に定義したGUEST_USER_EMAIL("guest@example.com")かどうかを判断し、
正しければtrueを、異なっていればfalseを返します。
メソッドを使用した下記記述に変更していく。
app/views/users/_info.html.erb
<% unless user.guest_user? %>
app/controllers/users_controller.rb
if @user.guest_user?
このようにメソッドを作成することで、ゲストユーザーの判定処理を変更する場合、
このメソッドだけを修正すれば良いため、保守性に優れています。
以上。