タイトルが長い。フレンドリーフォワーディングについてまとめます。
フレンドリーフォワーディングとは
「Youがリクエストしたページ、ログイン後のページなんだけど、まだログインしてないじゃん。ログインしてから行きたかったページに案内してあげるね」という類の処理です。よくお見かけする親切設計。きめ細かいです。
どうやって作るの?
大まかな流れとしては次のようになります。
* ログインしていないユーザーがきたとき
1. リクエストされたURLを一時保存する
2. ログイン画面に飛ばしてログイン確認
3. リクエストされていたURLに戻す
メソッド定義
リクエストを一時保存するためのメソッド(1)と一時保存したURLに戻すためのメソッド(3)を用意します。今回はsessions_helper.rb
内に、以下のように書きます。
# 1. リクエストされたURLを一時保存する
def store_location
session[:forwarding_url] = request.original_url if request.get?
end
# 3. リクエストされていたURLに戻す
def redirect_back_or(default)
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
end
1でsession[:forwarding_url]
として、リクエストされたURL(request.original_url)を保存します。 if request.get?
でリクエストの種類をGETアクションにのみ限定してあります。
3は一時保存したURLに戻す、あるいはデフォルトとして指定するURLに戻すための処理です。URLが存在しない場合も考慮して||
以降でdefaultで設定したURLを入れられるようにしています。
また、セッション情報を保持したままにしておくと、次のログインの時もこれを読み込んでおかしなことになるので、メソッド内2行目のsession.delete(:forwarding_url)
で一時保存したURLを削除します。
リクエストされたURLを一時保存 + ログイン確認
アクセスしようとしたURLを一時的に保存するためにstore_location
を呼び出ていきます。
ここではusers_controller.rb
のprivate以下、ログインしているユーザーがどうかを確認する記述とあわせて書いていきます。
class UsersController < ApplicationController
before_action :user_login_required
・
・
・
private
def user_login_required
unless logged_in? # ログインしていないとき
store_location # ここでURLを一時保存!
flash[:danger] = "ログインしてください" # フラッシュメッセージを表示
redirect_to login_url # ログインページに強制的に送る
end
end
リクエストされていたURLに戻す
ログイン後の遷移先をredirect_back_or(default)
を使って指定していきます。ログイン処理を行なっている箇所に次のように書けばOKです。
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
flash[:success] = "ログインしました"
# 以下でリダイレクト先を指定。defaultは、ここではuserを使いまわしているが user_url のように書くことができる
redirect_back_or user
else
flash.now[:danger] = 'ログインに失敗しました'
render 'new'
end
end
以上で実装完了です!
存在するURLからあえて強制送還をくらった後にログインしてみると、そのURLに飛ぶようになっていると思います。おつかれさまでした。
さいごに
以上、それぞれの役割が一目でわかりやすいように、自分なりにまとめ直してみました。少しでも参考になればうれしいです。
実装にあたり以下を参考にさせていただきました。ありがとうございました。