ゲストログイン機能の実装

ゲストログイン機能の実装

今回は以前作成したアプリケーションにゲストログイン機能を実装していく。

使用するアプリケーション 参考URL 作成するアプリケーションについて - takifugu’s blog

前提条件

GemのDeviseを使用(導入済み)

仕様

  • トップページにゲストログインボタンを配置する。

  • ゲストログインボタンを押すと、ゲストユーザーでログイン状態となり、ユーザー詳細画面に遷移する。

  • ゲストユーザーのnameとemailは事前に作成しておく。

  • ゲストユーザーはユーザー編集機能を使用できないようにする。(ユーザー編集ボタンの削除、アクセス制限の実装)

実装手順

  1. ゲストログインメソッドの作成

  2. ルーティングの記述

  3. ゲストメソッドの定義

  4. ゲストログインボタンの作成

  5. ゲストログイン時、ユーザ編集ボタンの非表示

  6. ゲストユーザーのユーザー編集へのアクセス制限の実装

ゲストログイン機能の実装

ゲストログインメソッドの作成

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?

このようにメソッドを作成することで、ゲストユーザーの判定処理を変更する場合、

このメソッドだけを修正すれば良いため、保守性に優れています。

以上。