I managed to get rid of the redirect loop mentioned, and make the routing a bit more robust and friendly-forwarding-ish, by doing the following (I used this example when I attempted to internationalize the Rails Tutorial:
config/routes.rb
ruby
SampleApp::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
ruby
require 'spec_helper'
describe "Routes"do
describe "locale scoped paths"doI18n.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)
endend
describe "redirecting", type::requestdo
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)) }
endendendend
describe "non-locale scoped paths"do
describe "redirecting", type::requestdo
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) }
endend
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_localeendendendend
I know that redirects are technically requests and their tests should really be under the spec/requests/ directory, but I figured they'd be more appropriate under routing since they're really just tests for exceptions and catch-alls. Anyway, hope this helps or is of interest to someone.
I managed to get rid of the redirect loop mentioned, and make the routing a bit more robust and friendly-forwarding-ish, by doing the following (I used this example when I attempted to internationalize the Rails Tutorial:
config/routes.rb
Since there are two
root_path
s, 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
I know that redirects are technically requests and their tests should really be under the spec/requests/ directory, but I figured they'd be more appropriate under routing since they're really just tests for exceptions and catch-alls. Anyway, hope this helps or is of interest to someone.