0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

はじめに

こんにちは。アメリカに住みながら独学でエンジニアを目指している taira です。
現在Ruby on Railsを使用して学習中ですが、そこで出てきたフレンドリーフォワーディングについて自分なりに整理してみました

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

フレンドリーフォワーディングとは、「ログインが必要なページ」にアクセスしようとした未ログインユーザーを一度ログインページに誘導した後、ログインが成功したら最初にアクセスしようとしたページへ自動的に戻す仕組みです。
ユーザー体験を向上するために取り入れる仕組みになっています。

例を挙げると、以下のような状況でフレンドリーフォワーディングを行います

  1. 未ログインのユーザーが「プロフィール編集ページ」にアクセス。
  2. ログインしていないのでログインページに強制リダイレクト。
  3. ユーザーがログインすると、再び「プロフィール編集ページ」へと自動的に遷移する。

実装方法

Railsチュートリアルでは、コードの実装の前にテストコードを書いています。
テストコードはシンプルなので、詳しくは本編をご覧ください。

実装の手順としては以下の通りです。

  1. sessions_helper.rbsessionにログイン画面に飛ぶ前のリンクを保存するstore_locationメソッドを定義する
  2. users_controller.rbstore_locationを呼び出す
  3. sessions_controller.rbcreateメソッド(ログインボタンを押したときに呼び出される)に、store_locationメソッドで保存したURLを呼び出し、リダイレクトする。

1. sessions_helper.rbsessionにログイン画面に飛ぶ前のリンクを保存するstore_locationメソッドを定義する

module SessionsHelper
 .
 .
 .
  #アクセスしようとしたURLを保存する
  def store_location
    session[:forwarding_url]= request.original_url if request.get?
  end
end

request.original_urlを使用することで、ログイン画面にリダイレクトする前のURLを取得することができます。
request.get?としているのは、例えばDELETEリクエストのリンクを取得してしまったら、ログインしたのに情報が削除されるという予期しない動作をすることになるので、GETメソッドのみにしています

2. users_controller.rbstore_locationを呼び出す

#ログイン済みユーザーかどうか確認
def logged_in_user
  unless logged_in?
    store_location # 追加
    flash[:danger]= "Please login."
    redirect_to login_url, status: :see_other
  end
end

redirect_to でログイン画面にリダイレクトするので、その前にstore_locationメソッドでsession[:forwarding_url]でリンクを保存しておきます

3. sessions_controller.rbcreateメソッド(ログインボタンを押したときに呼び出される)に、store_locationメソッドで保存したURLを呼び出し、リダイレクトする。

def create
  user = User.find_by(email:params[:session][:email].downcase)
  if user && user.authenticate(params[:session][:password])
    forwarding_url = session[:forwarding_url] # 追加
    reset_session
    params[:session][:remember_me] == '1' ?remember(user) :forget(user)
    log_in user
    redirect_to forwarding_url || user # 追加
  else
    flash.now[:danger] = 'Invalid email/password combination'
    render 'new', status: :unprocessable_entity
  end
end

上記のforwarding_urlの位置ですが、reset_sessionの後だとセッションがリセットされてしまった後になるので、その前にローカル変数に代入する必要があります。
redirect_toforwarding_urlに値が入っていれば、ログイン前に飛ぼうとしたリンクへリダイレクトします。

リダイレクトでほかのページに飛ぶことはできないのか

redirect_to edit_user_path(@user)のように決まった場所にリダイレクトしてしまえば、わざわざURLを保存する必要はないのでは?と最初見たときは思いました。
実際にすることは可能ですが、わざわざ元のURLを一度保存してまでフレンドリーフォワーディングを使う主な理由は、**「ログインが必要なページがひとつではなく、たくさんあるため」**です。

例えば、次のような状況を考えます。

あなたのRailsアプリに以下のページがあるとします

  • プロフィール編集ページ(edit_user_path
  • 投稿作成ページ(new_post_path
  • 設定変更ページ(settings_path
  • 特定の投稿の編集ページ(edit_post_path(post)

上記すべてログインを要求するページである場合を想像してみましょう。

もしURLを保存しない方法を取った場合、どうなるでしょうか?

edit_user_path にアクセス → ログイン要求 → ログイン後に redirect_to edit_user_pathでOK
しかし、new_post_pathにアクセス → ログイン要求 → ログイン後、edit_user_pathに戻される?
後者の場合、ユーザーが望んだページと異なるページへ遷移するため、ユーザーにとって混乱やストレスになります。
ページごとに決め打ちのredirect_toを設定していては、すべてのパターンを網羅する必要があり、コードも複雑化します。

まとめ

フレンドリーフォワーディングによって、ユーザーはログイン後に元々アクセスしようとしていたページへスムーズに戻ることができます。これにより複数のページでログインを要求する場面でも、ユーザーの混乱や操作の手間を軽減することが可能です。実装方法は比較的シンプルであり、Railsチュートリアルを参考にしながら、自身のアプリケーションに合わせてカスタマイズしてみてください。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?