LoginSignup
6
9

More than 3 years have passed since last update.

【Rails】ログインしていないユーザーのリクエストURLを一時保存して、ログイン後にそのURLに戻す方法

Posted at

タイトルが長い。フレンドリーフォワーディングについてまとめます。

フレンドリーフォワーディングとは

「Youがリクエストしたページ、ログイン後のページなんだけど、まだログインしてないじゃん。ログインしてから行きたかったページに案内してあげるね」という類の処理です。よくお見かけする親切設計。きめ細かいです。

どうやって作るの?

大まかな流れとしては次のようになります。

* ログインしていないユーザーがきたとき
 1. リクエストされたURLを一時保存する
 2. ログイン画面に飛ばしてログイン確認
 3. リクエストされていたURLに戻す

メソッド定義

リクエストを一時保存するためのメソッド(1)と一時保存したURLに戻すためのメソッド(3)を用意します。今回はsessions_helper.rb内に、以下のように書きます。

helpers/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以下、ログインしているユーザーがどうかを確認する記述とあわせて書いていきます。

users_controller.rb

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です。

controllers/sessions_controller.rb

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に飛ぶようになっていると思います。おつかれさまでした。

さいごに

以上、それぞれの役割が一目でわかりやすいように、自分なりにまとめ直してみました。少しでも参考になればうれしいです。

実装にあたり以下を参考にさせていただきました。ありがとうございました。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9