質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Devise

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

4099閲覧

【Rails】【devise関連?】一定条件でかかるリダイレクト処理を一定画面だけ除外したい

gogoackman3

総合スコア109

Devise

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

1グッド

2クリップ

投稿2016/10/24 15:38

今、以下のような新規登録フォームを作成しています。

①アカウント登録(メアド/Twitter)
②プロフィール設定
③登録完了

■仕様
①が完了した時点でUsersテーブルにデータが追加され実質ログイン状態となります。
①完了後、画面から離脱→再方→②から再開という場合に備えたい。

そのために、①が完了していて、②が完了していないユーザーがログインしてきた場合は、自動的に②の画面に遷移させています。

それが、ApplicationController内に以下のようなメソッドになります。

before_action :fix_user_sign_up_detail

▼ApplicationController

ruby

1class ApplicationController < ActionController::Base 2 protect_from_forgery with: :exception 3 4 before_action :fix_user_sign_up_detail 5 before_action :store_current_location 6 before_action :configure_permitted_parameters, if: :devise_controller? 7 8 private 9 10 def fix_user_sign_up_detail 11 redirect_to edit_user_registration_detail_path if user_signed_in? && current_user.handle_name.blank? 12 end 13 14 def store_current_location 15 store_location_for(:user, request.url) 16 end 17 18 protected 19 def configure_permitted_parameters 20 devise_parameter_sanitizer.permit(:sign_up, keys:[:email]) 21 devise_parameter_sanitizer.permit(:sign_in, keys:[:login, :handle_name]) 22 devise_parameter_sanitizer.permit(:account_update, keys:[:handle_name, :email, :password, :password_confirmation, :current_password]) 23 end 24end 25

ただ、これだと、②の画面に遷移した時にもリダイレクトがかかり、②の画面の無限ループに陥ります。

それを回避する施策で、Users::RegistrationsControllerにて以下のメソッドを追加しています。

prepend_before_action :authenticate_scope!, only: [:edit_detail, :update_detail]

ruby

1class Users::RegistrationsController < Devise::RegistrationsController 2 3 prepend_before_action :authenticate_scope!, only: [:edit_detail, :update_detail] 4 5 # Twitter/メアドの選択画面 6 def select 7 end 8 9 # GET /resource/sign_up 10 def new 11 super 12 end 13 14 # ②の画面。名前やプロフィールを設定する。 15 def edit_detail 16 end 17 18 def update_detail 19 resource_updated = resource.update(detail_params) 20 if resource_updated 21 @modal = {name: 'update-detail-modal'} 22 end 23 render :edit_detail 24 end 25 26 27 28 protected 29 30 def detail_params 31 params.require(:user).permit(:icon, :handle_name, :profile) 32 end 33 34 # The path used after sign up. 35 def after_sign_up_path_for(resource) 36 edit_user_registration_detail_path 37 end 38 39end

しかしながら、edit_user_registration_detail_path(②の画面。edit_detailアクションのViewです。)に遷移するとリダイレクトの無限ループになります。

これってそもそも、prepend_before_action :authenticate_scope!, only: [:edit_detail, :update_detail]の解釈が誤っていますか??つまり、リダイレクト(before_action :fix_user_sign_up_detail)を適用外にする効力は持っていない??

もし、その場合、どのような方法で、edit_detailとupdate_detailで無限ループに陥るのを回避出来ますでしょうか??

※before_action :fix_user_sign_up_detail,except:%w( edit_detail update_detail )でも回避出来る?と思いますが、あまり良い方法に思えず、これ以外の方法が知りたいのです。

Yuinyan👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

before_action の if: オプションを使う手もありますね。

ruby

1class ApplicationController < ActionController::Base 2 before_action :fix_user_sign_up_detail, if: :needed 3 4 private 5 6 def needed 7 true 8 end 9end

ruby

1class Users::RegistrationsController < Devise::RegistrationsController 2 private 3 4 def needed 5 false 6 end 7end

(メソッド名はもうちょっとマシな名前にしてあげてください)


①この方法でコントローラー毎ではなく、アクション毎のスキップは出来ないでしょうか?

できますよ。 #needed をそのように実装してあげればいいだけです。

ruby

1def needed 2 params[:action] != 'kino_action_ha_skip' 3end

②結局のところ、prepend_before_action :authenticate_scope!, only: [:edit_detail, :update_detail] というメソッドでは、アクション毎にbefore_actionをskip出来ないのでしょうか??

before_action は通常書く度に後ろに追加されていきますが prepend_before_action は先頭に追加されていくというのが違いという風に思っています。

なぜskipするのに使えると思ったのかがわからないので、なんとも言えないですが、prepend_before_action で登録済の action をキャンセルする方法は僕はわかりません。ごめんなさい。

投稿2016/10/24 23:23

編集2016/10/25 01:21
hana-da

総合スコア1728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gogoackman3

2016/10/25 01:08

ありがとうございます!2点ありまして、 ①この方法でコントローラー毎ではなく、アクション毎のスキップは出来ないでしょうか? 調べたところ、コントローラー毎で制御出来るのは理解出来ました。 https://blog.hello-world.jp.net/ruby/2637/ ②結局のところ、prepend_before_action :authenticate_scope!, only: [:edit_detail, :update_detail] というメソッドでは、アクション毎にbefore_actionをskip出来ないのでしょうか??
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問