deviseを使ってゲストログイン機能を実装する
はじめに
こんにちは!bosatoです!
この記事は30代未経験でwebエンジニアを目指し、現在スクールで勉強中の私が、勉強中にカリキュラムでは理解が難しかったことや、これってどうなの?って部分をアウトプットのために書いている記事です。この記事が僕と同じ境遇の人の役に立てば幸いです。
最近クラウドを勉強して、だんだん用語の意味を忘れてきてしまったり、ごちゃごちゃになってきたので必要最低限の知識を整理の意味でアウトプットしていこうと思います。
仕様の確認
- トップページにゲストログイン機能を作成する
- ゲストログインボタンを押すと、ゲストユーザーでログイン状態になり、ユーザー詳細画面へ遷移する
- nameとemailは決めておく
- ゲストログインユーザーはプロフィール編集画面への遷移ボタンを配置しない
- ゲストログインユーザーはプロフィール編集画面へ遷移できない
- 前提としてDeviseの機能を応用して実装する
ゲストログイン機能の作成
deviseのログイン機能はsessions_controller.rbに記載されており、このdeviseの機能を継承してゲストログイン機能を実装していきます。
アクションの定義
- app/controllersの配下にusersフォルダを作成し、sessions_controller.rbを作成。
*adminも作成している場合は、publicフォルダにすることが多い - sign_in userでゲストをログイン状態にさせる
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
ルーティングの設定
config/routes.rb
devise_scope :user do
post "users/guest_sign_in", to: "users/sessions#guest_sign_in"
end
modelに記述
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
end
user.rbにapp/controllers/users/sessions_controller.rbで記述したUser.guestのguestメソッドを定義しています。
find_or_create_by!はデータの検索と作成を指導的に判断して処理を行うメソッド。
パスワードはSecureRandom.urlsafe_base64でランダムな文字列にすることができる。
name部分わかりやすいようにguestuserにします。
機能部分の作成は以上になります。
ゲストログインボタンを配置する
ログインボタンと新規作成ボタンの上に配置することにします。
app/views/homes/top.html.erb
<%= link_to "ゲストログイン(閲覧用)", users_guest_sign_in_path, method: :post %>
ここまででゲストログイン機能の実装は完了です。
プロフィール編集を行えないようにする
やること
- ゲストユーザーでログインしているときにはプロフィール編集画面のボタンを表示しない
- 編集画面へのURL直打ちにも対応させる
Viewの編集
app/views/users/***.html.erb
<% if user.email != "guest@example.com" %>
<%= link_to edit_user_path(user) %>
<% end %>
***は自分の環境に合わせましょう。
ユーザーのemailがguest@example.comではない場合には、ボタンを表示して、ユーザーのemailがguest@example.comである場合には、表示しないようにします。
他にも
<% if !user.guest_user? && user == current_user %>
<%= link_to "プロフィール編集", edit_user_path(user) %>
<% end %>
対象のuserがゲストユーザーではなく、かつ、現在ログインしているユーザーと同じである場合という条件分岐もできます。このコードでも成立しました。
直打ち対策
ユーザーの編集画面へのURLを直接入力された場合にはメッセージを表示してユーザー詳細画面へリダイレクトさせます。
app/controllers/users_controller.rbへメソッドを作成し、before_actionでeditアクション実行前に処理を行います。
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :ensure_guest, only: [:edit]
:
:
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/controllers/users_controller.rbとapp/views/users/***.html.erbでゲストユーザーであるかの判別をしているので、この判定処理をapp/models/user.rbにインスタンスメソッドとして定義して利用していきます。
```ruby
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
def guest_user?
email == GUEST_USER_EMAIL
end
:
:
guest_user?というメソッドでは、メールアドレスがゲストユーザーのものであるかを判定しtrueかfalseの値を返します。
これを条件分岐に使用し、コードをブラッシュアップします。
app/controllers/users_controller.rb
:
:
private
:
:
def ensure_guest_user
@user = User.find(params[:id])
if @user.guest_user?
redirect_to user_path(current_user) , notice: 'ゲストユーザーはプロフィール編集画面へ遷移できません。'
end
end
:
:
app/views/users/***.html.erb
:
:
<% unless user.guest_user? %>
<%= link_to '',edit_user_path(user) %>
<% end %>
guest_user?というメソッドを定義することで、複数の箇所で同じメソッドを共有することができます。
まとめ
- controllerにアクション定義
- routes.rbを編集 devise_scope
- modelsにguestメソッドを定義
- viewにゲストログインボタンを設置
- viewにプロフィール編集を行えないよう条件分岐書く
- controllerにbefore_actionで直打ち対策する
- コードをブラッシュアップ
Discussion