Devise and I18n - reset password routing issues

此生再无相见时 提交于 2019-12-06 11:48:47

问题


I added I18n to my RoR app that is using Devise and I am now getting an error if I try to do a password reset. The error is:

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

How can I correctly set up my Devise routing to account for I18n?

routes.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

回答1:


I did create a sample app exactly for this situation (devise + internationalization). It has been time since i created that application, and probably it is little buggy/incomplete, but the key point is using optional scope with parenthesis.

The problem with your code, devise_for :users is not defined when you dont have :locale variable set (this is what im guessing from your error, redirection code in your routes is probably not working - you really dont need that, i did not tested, but i dont think this is a good practise). Also, that's why it is trying to assign token value as :locale variable.

Instead, you need to use parentheses. So that :locale will be optional, and your route definitions will remain valid when :locale is not set.

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

I hope it helps.




回答2:


I had the same problem (getting routing error on password reset), but here is the solution I found: Routing error is caused not by controllers or any other Devise internal processes but by a view. In views/devise/mailer/reset_password_instructions.html.erb the line:

<%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>

Needs to be replaced to:

<%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token, :locale => I18n.locale) %>`

I don't know why the locale parameter isn't added by default.




回答3:


I don't really know much about setting up Devise, but I did spend a bit of time looking in to internationalizing Rails routing, so hopefully this answer will be of use to you, if not as an answer to your question, then as a reference in getting closer to the answer (the content mostly a rehash of a comment I wrote in the comments for the i18n Railscast, which is also a good source of Rails i18n routing info):

Your application_controller.rb looks fine to me, but perhaps try changing your routes.rb to look something like this:

config/routes.rb (example)

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

Since there are two root_paths, I renamed the one inside the :locale scope so there would be no conflicts in the app and tests. I tested the routes using RSpec as follows:

spec/routing/routing_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


来源:https://stackoverflow.com/questions/11900085/devise-and-i18n-reset-password-routing-issues

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!