読者です 読者をやめる 読者になる 読者になる

【Rails】URLでlocaleがある場合、Deviseのリダイレクトでlocaleが外れてしまう

Railsで管理画面を作っている際に発見した現象をメモ

現象

以下の様なルーティングを設定した場合
※ディレクトリは自分でわかりやすいようにカスタマイズしています。

Rails.application.routes.draw do

  scope "(:locale)" do
    namespace :admin do
      devise_for :admin_users, controllers: { sessions: 'admin/devise/sessions' }
      get '/', :to => 'home#index'
    end
  end
end

ルーティングは以下のようになります。
※ディレクトリは自分でわかりやすいようにカスタマイズしています。

        new_admin_admin_user_session GET    (/:locale)/admin/admin_users/sign_in(.:format)       admin/devise/sessions#new
            admin_admin_user_session POST   (/:locale)/admin/admin_users/sign_in(.:format)       admin/devise/sessions#create
    destroy_admin_admin_user_session DELETE (/:locale)/admin/admin_users/sign_out(.:format)      admin/devise/sessions#destroy
                               admin GET    (/:locale)/admin(.:format)                           admin/home#index

ApplicationControllerは、以下の通り

class ApplicationController < ActionController::Base

  before_action :set_locale

  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
  end

  def default_url_options(options = {})
    { locale: I18n.locale }.merge options
  end

  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
end

この設定で、未ログインで管理画面に行くとログイン画面に
リダイレクトされるのですが、URLのlocaleが外れてしまいます。

解決策

ApplicationControllerに以下の記述をすれば、localeが外れずに済むようです。

  def self.default_url_options
    { :locale => I18n.locale }
  end

ただし、なぜクラスメソッドにすると大丈夫なのか理由がわからず・・・
こういうところをスムーズに解決、理由を話せるようになりたいです。

stackoverflow.com