Why rails app is redirecting unexpectedly instead of matching the route?

佐手、 提交于 2019-11-30 23:47:13

We meet again, ruevaughn. :)

I created a test rails app and the following minimal example works for me:

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
  resources :sites do
    collection do
      get :admin
    end
  end

  root to: "locale#root" # handles /en/
  match "*path", to: "locale#not_found" # handles /en/fake/path/whatever
end

root to: redirect("/#{I18n.default_locale}") # handles /
match '*path', to: redirect("/#{I18n.default_locale}/%{path}") # handles /not-a-locale/anything

When using Rails 4.0.x that %{path} in the redirect will escape slashes in the path, so you will get an infinite loop redirecting to /en/en%2Fen%2Fen%2Fen...

Just in case someone, like me, is looking for a Rails-4-suitable solution, this is what I found to be working without problems, even with more complex paths to be redirected:

# Redirect root to /:locale if needed
root to: redirect("/#{I18n.locale}", status: 301)

# Match missing locale paths to /:locale/path
# handling additional formats and/or get params
match '*path', to: (redirect(status: 307) do |params,request|
  sub_params = request.params.except :path
  if sub_params.size > 0
    format = sub_params[:format]
    sub_params.except! :format
    if format.present?
      "/#{I18n.locale}/#{params[:path]}.#{format}?#{sub_params.to_query}"
    else
      "/#{I18n.locale}/#{params[:path]}?#{sub_params.to_query}"
    end
  else
    "/#{I18n.locale}/#{params[:path]}"
  end
end), via: :all

# Redirect to custom root if all previous matches fail
match '', to: redirect("/#{I18n.locale}", status: 301), via: :all
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!