deviseでlocaleが維持されない場合があったので対処
ユーザー認証にdeviseを使っているのだけれどlocaleパラメーターがデフォルトのlocaleに戻ってしまう場合があった。
具体的には既にログインしている状態でsign_in,sign_upページに遷移しようとした場合。リダイレクトされて「You are already signed in.」というフラッシュメッセージが表示されるのだけれどlocaleをjpにして遷移してもリダイレクト後のページはデフォルトのlocaleのページになってしまう。
公式Wikiに How To: Redirect with locale after authentication failure というのがあるけれど認証に失敗している訳ではないしその通りにしても効果無し。
処理を追いかけてみたところI18n.localeを設定しているフィルターが実行される前にリダイレクトされている模様。deviseのソースコード(v2.2.4)を見てみるとDevise::RegistrationsControllerでprepend_before_filterされているrequire_no_authenticationでリダイレクトされていた。
なんとかしてlocaleを設定する(set_locale)フィルターをrequire_no_authenticationフィルターより先に実行したいのだが…良い方法がわからなかった。
ApplicationControllerでprepend_before_filter: :set_localeとしてもDevise::*ControllerはApplicationControllerを継承したDeviseControllerを継承してprepend_before_filter: :require_no_authenticationしているのでrequire_no_authenticationが先に実行されてしまう。
しかたがないのでDivese::*Controllerを継承したControllerを用意してprependし直すことにした。
# config/routes.rb scope '(:locale)' do devise_for :users, :skip => [:registration], :controllers => { :sessions => "mydevise/sessions", :passwords => "mydevise/passwords", :unlocks => "mydevise/unlocks", } devise_scope :user do resource :registration, only: [:new, :create, :edit, :update], path: 'users', path_names: { new: 'sign_up' }, controller: 'mydevise/registrations', as: :user_registration do get :cancel end end end
# app/controllers/mydevise/sessions_controller.rb # 他のDevise::*Controllerも同様 class Mydevise::SessionsController < Devise::SessionsController skip_before_filter :set_locale prepend_before_filter :set_locale end
とりあえずこれでlocaleは維持されるようになったが…どなたかもっと良い解決方法をご存知の方がおられましたらお教えください。