Исходная форма этого ответа сильно отличается, и ее можно найти здесь . Просто доказательство того, что есть несколько способов снять шкуру с кошки.
С тех пор я обновил ответ, чтобы использовать пространства имен и редирект 301, а не 302 по умолчанию. Спасибо pixeltrix и Bo Jeanes за подсказки по этим вопросам.
Возможно, вы захотите надеть действительно прочный шлем, потому что он взорвет ваш мозг .
API маршрутизации Rails 3 супер злой. Чтобы написать маршруты для вашего API в соответствии с вашими требованиями выше, вам понадобится только это:
namespace :api do
namespace :v1 do
resources :users
end
namespace :v2 do
resources :users
end
match 'v:api/*path', :to => redirect("/api/v2/%{path}")
match '*path', :to => redirect("/api/v2/%{path}")
end
Если после этого момента ваш разум еще не пострадал, позвольте мне объяснить.
Во-первых, мы вызываем namespaceэто очень удобно, когда вы хотите, чтобы группа маршрутов была привязана к определенному пути и модулю с одинаковыми именами. В этом случае мы хотим, чтобы все маршруты внутри нашего блока namespaceбыли привязаны к контроллерам внутри Apiмодуля, и все запросы к путям внутри этого маршрута будут иметь префикс api. Такие запросы, как /api/v2/users, знаете?
Внутри пространства имен мы определяем еще два пространства имен (воах!). На этот раз мы определяем в «v1» пространство имена, поэтому все маршруты для контроллеров здесь будут внутри V1модуля внутри Apiмодуля: Api::V1. Определив resources :usersвнутри этого маршрута, контроллер будет расположен по адресу Api::V1::UsersController. Это версия 1, и вы попадаете туда, выполняя запросы вроде /api/v1/users.
Версия 2 является лишь крошечной немного по- другому. Вместо того, чтобы обслуживающий его контроллер Api::V1::UsersController, теперь он находится в Api::V2::UsersController. Вы попадаете туда, делая запросы вроде /api/v2/users.
Далее используется a match. Это будет соответствовать всем маршрутам API, которые относятся к таким вещам, как /api/v3/users.
Это та часть, которую я должен был найти. Эта :to =>опция позволяет вам указать, что конкретный запрос должен быть перенаправлен куда-то еще - я это знал, но я не знал, как заставить его перенаправить куда-то еще и передать вместе с ним часть исходного запроса. .
Для этого мы вызываем redirectметод и передаем ему строку со специально-интерполированным %{path}параметром. Когда приходит запрос, соответствующий этому финалу match, он интерполирует pathпараметр в местоположение %{path}внутри строки и перенаправляет пользователя туда, куда ему нужно перейти.
Наконец, мы используем другой matchдля маршрутизации всех оставшихся путей с префиксом /apiи перенаправления на них /api/v2/%{path}. Это означает, что такие запросы /api/usersбудут отправлены в /api/v2/users.
Я не мог понять, как добиться /api/asdf/usersсовпадения, потому что как определить, должен ли это быть запрос к /api/<resource>/<identifier>или /api/<version>/<resource>?
В любом случае, это было интересно исследовать, и я надеюсь, что это поможет вам!