その他
    ホーム技術発信DoRubydevise ログイン後のリダイレクトについて(POST編)

    devise ログイン後のリダイレクトについて(POST編)

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    Rails の Devise でログイン後にログインする直前のPOSTリクエストにリダイレクトさせます。

     目標

    RailsでPOSTリクエストではリダイレクトできないため、deviserログイン後はGETリクエストのみリダイレクトできます。

    下記の場合、お気に入り登録が出来ないし、お気に入り一覧にリダイレクトできないです。

    未ログイン⇒商品詳細⇒お気に入り登録(POST)⇒ログイン画面⇒ログインする⇒お気に入り一覧

     対策

    POSTなので、直接遷移が出来なくて、after_login_to_postを作成して、その後自動サブミットすれば、POSTリクエストにリダイレクトを実現します。

    動き:

    未ログイン⇒商品詳細⇒お気に入り登録(POST)⇒ログイン画面⇒ログインする⇒after_login_to_post⇒真っ白ページ(自動サブミット)⇒お気に入り一覧

     セッションに POST リクエストのパラメータを保存

    POSTリクエスト中で、POSTリクエストのパラメータ、コントローラ、アクションをセッションに保存します。

    class CustomersFavoritesController < ApplicationController
      before_action :authenticate_customer!, except: :create
      def create
        if current_customer.signed_in?
          current_customer.favorites.create(product_id: params[:id]) unless current_customer.favorites.find_by(product_id: params[:id])
          redirect_to action: :index
        else
          #セッションに POST リクエストのパラメータを保存
          session[:after_login_to_post] = {
            controller_name: controller_name,
            action_name: action_name,
            params: { id: params[:id] }
          }
          redirect_to new_customer_session_path
        end
      end
    end
    

     ログイン後のリダイレクトをカスタマイズ

    ログイン後、セッションにPOST情報があれば、after_login_to_post_pathにリダイレクトさせます。

    class CustomersSessionsController < Devise::SessionsController
      # ログイン後、リダイレクト先メッソドafter_sign_in_path_forをオーバーライドする。
      def after_sign_in_path_for(resource)
       #お気に入り登録(POST)の場合、after_login_to_post_pathに遷移します。
        if session[:after_login_to_post]
          after_login_to_post_path
        else
          super
        end
      end
    end
    

     ログイン後にセッション情報からログイン直前のページ情報を復元

    セッション情報から、POSTリクエストの情報を取得し、設定します。

    class TopController < ApplicationController
      def after_login_to_post
       #セッションにafter_login_to_postがあれば、
        if session[:after_login_to_post]
          @back_controller = session[:after_login_to_post]['controller_name']
          @back_action = session[:after_login_to_post]['action_name']
          @params = session[:after_login_to_post]['params']
       #セッションをクリア
          session[:after_login_to_post] = nil
          render :after_login_to_post, layout: false
        else
          #直接アクセスが来たら、TOPに遷移する。
          redirect_to top_path
        end
      end
    end
    

     真っ白VIEW

    after_login_to_postのVIEWは自動サブミットします。

    一瞬だけ真っ白なページが表示されますが、

    自動サブミットによって、POST送信が出来ます。

    after_login_to_post.slim

    doctype transitional
    html[xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr"]
      head
        meta[http-equiv="Content-Type" content="text/html; charset=UTF-8"]
        title = '戻る'
      body onLoad="document.forms[0].submit()"
        - if @back_controller && @back_action && @params
          = form_tag( { controller: @back_controller, action: @back_action }, { method: 'post' } ) do
            = hidden_field_tag 'id', @params['id']
            <noscript>
            = button_tag '戻る', class: 'btn_sub'
            </noscript>
    

     routes

      ### ログイン後、POSTアクションに戻る ###
      get 'after_login_to_post', to: 'top#after_login_to_post'
    

     参照

    http://easyramble.com/cannot-post-redirect-on-rails.html