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 namespace
cuá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 namespace
tengan alcance para los controladores dentro del Api
mó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 V1
módulo en el interior del Api
módulo: Api::V1
. Al definir resources :users
dentro 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, match
se 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 redirect
mé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 path
parámetro en la ubicación %{path}
dentro de la cadena y redirigirá al usuario a donde debe ir.
Finalmente, usamos otro match
para enrutar todos los caminos restantes con el prefijo /api
y redirigirlos a ellos /api/v2/%{path}
. Esto significa que las solicitudes como /api/users
irán a /api/v2/users
.
No pude averiguar cómo llegar /api/asdf/users
a 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.