Исходная форма этого ответа сильно отличается, и ее можно найти здесь . Просто доказательство того, что есть несколько способов снять шкуру с кошки.
С тех пор я обновил ответ, чтобы использовать пространства имен и редирект 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>
?
В любом случае, это было интересно исследовать, и я надеюсь, что это поможет вам!