La forma original de esta respuesta es muy diferente, y se puede encontrar aquí . Solo prueba de que hay más de una forma de pelar un gato.
He actualizado la respuesta desde entonces para usar espacios de nombres y usar redireccionamientos 301, en lugar del valor predeterminado de 302. Gracias a pixeltrix y Bo Jeanes por sus comentarios.
Es posible que desee usar un casco realmente fuerte porque esto le dejará boquiabierto .
La API de enrutamiento Rails 3 es súper malvada. Para escribir las rutas para su API, según sus requisitos anteriores, solo necesita esto:
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
Si tu mente sigue intacta después de este punto, déjame explicarte.
Primero, llamamos namespacecuál es súper útil para cuando quieres un montón de rutas con alcance a una ruta específica y módulo que tengan un nombre similar. En este caso, queremos que todas las rutas dentro del bloque namespacetengan alcance para los controladores dentro del Apimódulo y todas las solicitudes a rutas dentro de esta ruta tendrán el prefijo api. Solicitudes como /api/v2/users, ¿sabes?
Dentro del espacio de nombres, definimos dos espacios de nombres más (¡woah!). Esta vez estamos definiendo el espacio de nombres "v1", por lo que todas las rutas para los controladores de aquí estarán dentro del V1módulo en el interior del Apimódulo: Api::V1. Al definir resources :usersdentro de esta ruta, el controlador se ubicará en Api::V1::UsersController. Esta es la versión 1, y llega allí haciendo solicitudes como /api/v1/users.
La versión 2 es sólo una pequeña poco diferente. En lugar de que el controlador esté sirviendo Api::V1::UsersController, ahora está en Api::V2::UsersController. Llegas allí haciendo solicitudes como /api/v2/users.
A continuación, matchse utiliza a. Esto coincidirá con todas las rutas API que van a cosas como /api/v3/users.
Esta es la parte que tuve que buscar. La :to =>opción le permite especificar que una solicitud específica se debe redirigir a otro lugar, lo sabía, pero no sabía cómo hacer que se redirigiera a otro lugar y pasar una parte de la solicitud original junto con ella. .
Para hacer esto, llamamos al redirectmétodo y le pasamos una cadena con un %{path}parámetro interpolado especial . Cuando llega una solicitud que coincide con esta final match, interpolará el pathparámetro en la ubicación %{path}dentro de la cadena y redirigirá al usuario a donde debe ir.
Finalmente, usamos otro matchpara enrutar todos los caminos restantes con el prefijo /apiy redirigirlos a ellos /api/v2/%{path}. Esto significa que las solicitudes como /api/usersirán a /api/v2/users.
No pude averiguar cómo llegar /api/asdf/usersa una coincidencia, porque ¿cómo se determina si se supone que es una solicitud /api/<resource>/<identifier>o /api/<version>/<resource>?
De todos modos, esto fue divertido de investigar y espero que te ayude.