Создание маршрутов с необязательным префиксом пути
-
03-07-2019 - |
Вопрос
Как я могу добиться того, чтобы мои маршруты распознавали необязательный параметр prefix следующим образом:
/*lang/controller/id
В том смысле, что часть lang является необязательной и имеет значение по умолчанию, если оно не указано в URL:
/en/posts/1 => lang = en
/fr/posts/1 => lang = fr
/posts/1 => lang = en
Редактировать
В идеале я собираюсь сделать это для многих контроллеров и действий, сопоставив пространство имен:
map.namespace "*lang" do |lang|
lang.resources :posts
lang.resources :stories
end
Решение
Хорошо, мне удалось решить эту проблему:
По умолчанию в Rails это невозможно (по крайней мере, пока). Вместо использования пространств имен и значений по умолчанию мне нужно было установить фильтр маршрутизации Свена Фукса . р>
После установки плагина я добавил следующий файл в мою директорию lib:
require 'routing_filter/base'
module RoutingFilter
class Locale < Base
# remove the locale from the beginning of the path, pass the path
# to the given block and set it to the resulting params hash
def around_recognize(path, env, &block)
locale = nil
path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end
returning yield do |params|
params[:locale] = locale || 'en'
end
end
def around_generate(*args, &block)
locale = args.extract_options!.delete(:locale) || 'en'
returning yield do |result|
if locale != 'en'
result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" }
end
end
end
end
end
Я добавил эту строку в route.rb:
map.filter 'locale'
Это в основном заполняет хук до и после, генерируемый плагином, который оборачивает маршрутизацию рельсов. Р>
Когда URL-адрес распознан, и до того, как Rails что-то с ним сделает, вызывается метод around_recognize. Это извлечет двухбуквенный код, представляющий локаль, и передаст его в параметрах по умолчанию «en», если локаль не указана.
Аналогичным образом, при создании URL-адреса параметр локали будет вставлен в URL-адрес с левой стороны.
Это дает мне следующие URL и сопоставления:
/ => :locale => 'en'
/en => :locale => 'en'
/fr => :locale => 'fr'
Все существующие помощники URL работают как прежде, с той лишь разницей, что, если не указан языковой стандарт, он сохраняется:
home_path => /
home_path(:locale => 'en') => /
home_path(:locale => 'fr') => /fr
Другие советы
Вы можете определить значения по умолчанию в маршруте с помощью клавиши : defaults
. Попробуйте это:
map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show',
:defaults => { :lang => 'en' }
Я понимаю, что это старый вопрос, но он может быть полезен.
map.with_options(:path_prefix => ":locale") do |m|
m.resources :posts
m.resources :stories
end
И вы должны добавить фильтр before в контроллер приложения, чтобы определить языковой стандарт, например
before_filter :define_locale
def define_locale
if params[:locale] == nil
I18n.locale = 'en'
else
I18n.locale = params[:locale]
end
end
Я предполагаю (сейчас нет времени на тестирование), что это может сработать:
map.connect ':language/posts/:id', :controller => 'posts', :action => 'show'
map.connect 'posts/:id', :controller => 'posts', :action => 'show'
Хорошо, попробовал - работает, по крайней мере на Rails 2.1.1. Так что это хорошо. Однако идея «по умолчанию» не работает, и это позор, потому что это СУХОЙ.
Думаю, вы могли бы в одно время использовать [ключ] = > ноль, чтобы указать необязательный параметр. Что-то вроде:
map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil