Создание маршрутов с необязательным префиксом пути - PullRequest
22 голосов
/ 17 октября 2008

Как мне заставить мои маршруты распознавать необязательный параметр префикса следующим образом:

/*lang/controller/id

В этом случае lang-часть является необязательной и имеет значение по умолчанию, если оно не указано в URL-адресе:

/en/posts/1   => lang = en
/fr/posts/1   => lang = fr
/posts/1      => lang = en

EDIT

В идеале, я хочу сделать это на многих контроллерах и в действиях путем сопоставления пространства имен:

map.namespace "*lang" do |lang|
  lang.resources :posts
  lang.resources :stories
end

Ответы [ 5 ]

19 голосов
/ 21 октября 2008

ОК, мне удалось решить эту проблему:

По умолчанию это невозможно сделать в 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
2 голосов
/ 30 января 2010

Я понимаю, что это старый вопрос, но он может быть полезен.

  map.with_options(:path_prefix => ":locale") do |m|
    m.resources :posts
    m.resources :stories        
  end

И вы должны добавить перед фильтром в контроллер приложения, чтобы определить локаль, например

before_filter :define_locale

def define_locale
  if params[:locale] == nil
    I18n.locale = 'en'
  else
    I18n.locale = params[:locale]
  end
end
2 голосов
/ 17 октября 2008

Вы можете определить значения по умолчанию в маршруте с помощью клавиши :defaults. Попробуйте это:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show',
                               :defaults => { :lang => 'en' }
1 голос
/ 18 октября 2008

Думаю, вы могли бы в одно время использовать [key] => nil для указания необязательного параметра. Что-то вроде:

map.connect ':lang/posts/:id', :controller => 'posts', :action => 'show', :lang => nil
1 голос
/ 17 октября 2008

Я предполагаю (сейчас нет времени на тестирование), что это может сработать:

map.connect ':language/posts/:id', :controller => 'posts', :action => 'show'
map.connect 'posts/:id', :controller => 'posts', :action => 'show'

ОК, попробовал - работает, по крайней мере на Rails 2.1.1. Так что это хорошо. Не могу заставить идею работать по умолчанию: обидно, потому что это СУХОЙ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...