ror root_path restful rails examples ruby-on-rails ruby-on-rails-3 routes versioning

ruby-on-rails - root_path - routes ror



Control de versiones de API para rutas de rieles (6)

Estoy intentando versionar mi API como Stripe. A continuación se da la última versión de API es 2.

/api/users devuelve un 301 a /api/v2/users

/api/v1/users devuelve un índice de 200 usuarios en la versión 1

/api/v3/users devuelve un 301 a /api/v2/users

/api/asdf/users devuelve un 301 a /api/v2/users

De modo que básicamente todo lo que no especifique los enlaces de la versión a la última a menos que exista la versión especificada, entonces redirija a ella.

Esto es lo que tengo hasta ahora:

scope ''api'', :format => :json do scope ''v:api_version'', :api_version => /[12]/ do resources :users end match ''/*path'', :to => redirect { |params| "/api/v2/#{params[:path]}" } end


La respuesta de Ryan Bigg funcionó para mí.

Si también desea mantener los parámetros de consulta a través de la redirección, puede hacerlo así:

match "*path", to: redirect{ |params, request| "/api/v2/#{params[:path]}?#{request.query_string}" }


No estoy seguro de por qué quieres redirigir a una versión específica si no se solicita explícitamente una versión. Parece que simplemente quiere definir una versión predeterminada que se sirve si no se solicita explícitamente ninguna versión. También estoy de acuerdo con David Bock en que mantener las versiones fuera de la estructura de la URL es una manera más clara de respaldar el control de versiones.

Conector desvergonzado: Versionist admite estos casos de uso (y más).

https://github.com/bploetz/versionist


No soy un gran fan de versionar por rutas. Creamos VersionCake para admitir una forma más fácil de versiones de API.

Al incluir el número de versión de la API en el nombre del archivo de cada una de nuestras vistas respectivas (jbuilder, RABL, etc.), mantenemos el control de versiones discreto y permite una fácil degradación para admitir la compatibilidad con versiones anteriores (por ejemplo, si v5 de la vista no existe, render v4 de la vista).



Un par de cosas para agregar:

Su combinación de redirección no funcionará para ciertas rutas: el *api param es codicioso y lo tragará todo, por ejemplo, /api/asdf/users/1 lo redirigirá a /api/v2/1 . Sería mejor usar un parámetro normal como :api . Es cierto que no coincidirá con casos como /api/asdf/asdf/users/1 pero si tiene recursos anidados en su API es una mejor solución.

Ryan WHY U NO LIKE namespace ? :-), p.ej:

current_api_routes = lambda do resources :users end namespace :api do scope :module => :v2, &current_api_routes namespace :v2, &current_api_routes namespace :v1, &current_api_routes match ":api/*path", :to => redirect("/api/v2/%{path}") end

Que tiene el beneficio adicional de las rutas con nombre y con nombre genérico. Una nota adicional: la convención al usar :module es usar la notación de subrayado, por ejemplo: api/v1 no ''Api :: V1''. En un momento este último no funcionó, pero creo que se corrigió en Rails 3.1.

Además, cuando publica v3 de su API, las rutas se actualizarían así:

current_api_routes = lambda do resources :users end namespace :api do scope :module => :v3, &current_api_routes namespace :v3, &current_api_routes namespace :v2, &current_api_routes namespace :v1, &current_api_routes match ":api/*path", :to => redirect("/api/v3/%{path}") end

Por supuesto, es probable que tu API tenga diferentes rutas entre versiones, en cuyo caso puedes hacer esto:

current_api_routes = lambda do # Define latest API end namespace :api do scope :module => :v3, &current_api_routes namespace :v3, &current_api_routes namespace :v2 do # Define API v2 routes end namespace :v1 do # Define API v1 routes end match ":api/*path", :to => redirect("/api/v3/%{path}") end


La forma original de esta respuesta es muy diferente, y se puede encontrar aquí . Solo una prueba de que hay más de una manera de despellejar a un gato.

He actualizado la respuesta desde el uso de espacios de nombres y el uso de 301 redirecciones, en lugar del valor predeterminado de 302. Gracias a pixeltrix y Bo Jeanes por las indicaciones sobre esas cosas.

Es posible que desee usar un casco realmente fuerte porque esto va a volar su mente .

La API de enrutamiento de Rails 3 es muy perversa. 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.

En primer lugar, llamamos al namespace que es muy útil cuando se quiere un conjunto de rutas con un alcance específico y un módulo que se llame de manera similar. En este caso, queremos que todas las rutas dentro del bloque para nuestro namespace de namespace con alcance a los controladores dentro del módulo Api y todas las solicitudes a las rutas dentro de esta ruta se prefijan con 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 aquí estarán dentro del módulo V1 dentro del módulo Api::V1 : 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 se llega haciendo solicitudes como /api/v1/users .

La versión 2 es solo un poco diferente. En lugar de que el controlador sirva en Api::V1::UsersController , ahora está en Api::V2::UsersController . Llegas haciendo solicitudes como /api/v2/users .

A continuación, se usa una match . Esto coincidirá con todas las rutas API que van a cosas como /api/v3/users .

Esta es la parte que tuve que buscar. La opción :to => permite especificar que una solicitud específica debe ser redireccionada a otra parte, lo sabía, pero no sabía cómo redirigirla a otra parte y pasarle una parte del original. solicitar junto con ella.

Para hacer esto, llamamos al método de redirect y le pasamos una cadena con un parámetro %{path} especial interpolado. Cuando se recibe una solicitud que coincida con esta coincidencia final, se interpolará el parámetro de path en la ubicación de %{path} dentro de la cadena y se redirigirá al usuario al lugar al que debe dirigirse.

Finalmente, usamos otra match para enrutar todas las rutas restantes con el prefijo /api y redirigirlas a /api/v2/%{path} . Esto significa que las solicitudes como /api/users irán a /api/v2/users .

No pude encontrar la manera de hacer coincidir /api/asdf/users , porque ¿cómo se determina si se supone que es una solicitud a /api/<resource>/<identifier> o /api/<version>/<resource> ?

De todos modos, esto fue divertido de investigar y espero que te ayude!