2

Devise を使用している RoR アプリに I18n を追加しましたが、パスワードをリセットしようとするとエラーが発生します。エラーは次のとおりです。

Routing Error
No route matches {:action=>"edit", :controller=>"devise/passwords", :reset_password_token=>"uMopWesaxczNn2cdePUQ"} 

I18n を考慮して Devise ルーティングを正しく設定するにはどうすればよいですか?

ルート.rb

 scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do   
  devise_for :users, path_names: {sign_in: "login", sign_out: "logout"},
                   controllers: {omniauth_callbacks: "omniauth_callbacks"}
  root to: 'static_pages#home'
 end

   match '*path', to: redirect {|params| "/#{I18n.default_locale}/#{CGI::unescape(params[:path])}" }, constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" }
   match '', to: redirect("/#{I18n.default_locale}")

application_controller.rb

before_filter :set_locale
 def set_locale
   I18n.locale = params[:locale] if params[:locale].present?
 end

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

3 に答える 3

8

この状況(工夫+国際化)にぴったりのサンプルアプリを作成しました。そのアプリケーションを作成してから時間が経ちましたが、おそらく少しバグがあるか不完全ですが、重要な点は括弧付きのオプションのスコープを使用することです。

あなたのコードの問題は、変数が設定されdevise_for :usersていない場合に定義されていません:locale(これはあなたのエラーから推測したものです。ルートのリダイレクトコードはおそらく機能していません-あなたは本当にそれを必要としません、私はテストしませんでしたが、私は考えませんこれは良い習慣です)。:localeまた、トークン値を変数として割り当てようとしているのもそのためです。

代わりに、括弧を使用する必要があります。これ:localeはオプションであり、が設定されていない場合でもルート定義は有効なままです:locale

scope "(:locale)", :locale => /en|tr/ do
  devise_for :users
  root :to => "main#index"
end

お役に立てば幸いです。

于 2012-08-13T10:52:14.780 に答える
0

私はDeviseのセットアップについてあまり知りませんが、Railsルーティングの国際化について少し時間をかけて調べました。答えに近づくための参照 (内容は主に、i18n Railscast のコメントに書いたコメントの再ハッシュであり、Rails i18n ルーティング情報の良いソースでもあります):

application_controller.rbは問題ないように見えますが、routes.rb を次のように変更してみてください

config/routes.rb (例)

MyApp::Application.routes.draw do
  scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
    # ...
    match '/about',   to: 'static_pages#about'

    # handles /valid-locale
    root to: 'static_pages#home', as: "locale_root"
    # handles /valid-locale/fake-path
    match '*path', to: redirect { |params, request| "/#{params[:locale]}" }
  end

  # handles /
  root to: redirect("/#{I18n.default_locale}")
  # handles /bad-locale|anything/valid-path
  match '/*locale/*path', to: redirect("/#{I18n.default_locale}/%{path}")
  # handles /anything|valid-path-but-no-locale
  match '/*path', to: redirect("/#{I18n.default_locale}/%{path}")
end

が 2 つあるため、スコープroot_paths内の名前を変更:localeして、アプリとテストで競合が発生しないようにしました。次のように RSpec を使用してルートをテストしました。

仕様/ルーティング/ルーティング_spec.rb

require 'spec_helper'

describe "Routes" do

  describe "locale scoped paths" do
    I18n.available_locales.each do |locale|

      describe "routing" do
        it "should route /:locale to the root path" do
          get("/#{locale.to_s}").
            should route_to("static_pages#home", locale: locale.to_s)
        end
      end

      describe "redirecting", type: :request do

        subject { response }

        context "fake paths" do
          let(:fake_path) { "fake_path" }

          before { get "/#{locale.to_s}/#{fake_path}" }
          it { should redirect_to(locale_root_path(locale)) }
        end
      end
    end
  end

  describe "non-locale scoped paths" do

    describe "redirecting", type: :request do

      subject { response }

      context "no path given" do
        before { get "/" }
        it { should redirect_to(locale_root_path(I18n.default_locale)) }
      end

      context "a valid action" do
        let(:action) { "about" }
        let!(:default_locale_action_path) { about_path(I18n.default_locale) }

        context "with a valid but unsupported locale" do
          let(:unsupported_locale) { "fr" }

          before { get "/#{unsupported_locale}/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end

        context "with invalid information for the locale" do
          let(:invalid_locale) { "invalid" }

          before { get "/#{invalid_locale}/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end

        context "with no locale information" do
          before { get "/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end
      end

      context "invalid information" do
        let(:invalid_info) { "invalid" }

        before { get "/#{invalid_info}" }
        it { should redirect_to("/#{I18n.default_locale}/#{invalid_info}") }
        # This will then get caught by the "redirecting fake paths" condition
        # and hence be redirected to locale_root_path with I18n.default_locale
      end
    end
  end
end
于 2012-08-12T15:25:35.517 に答える