Actualmente estoy en el proceso de diseño de una API versionada para un nuevo sitio web. Entiendo cómo crear espacios de nombre de las rutas, pero estoy atascado en la mejor forma de implementar métodos versionados dentro de un modelo.Control de versiones de API en aplicaciones web
Los siguientes ejemplos de código están utilizando el marco de raíles, pero el principio de la cuestión debe ser coherente entre la mayoría de los marcos web.
Las rutas actualmente se ven algo como:
MyApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :products, :only => [:index, :show]
end
end
end
y el controlador:
class Api::V1::ProductsController < V1Controller
respond_to :json, :xml
def index
respond_with @products = Product.scoped
end
def show
respond_with @product = Product.find(params[:id])
end
end
Así que, obviamente, sólo estamos exponiendo los atributos disponibles en producto aquí, esta solución funciona muy bien si usted' Solo tendremos una versión de la API. ¿Qué sucede cuando desea liberar V2 y V2 necesita volver a implementar la forma en que se muestra el nombre del producto (manteniendo la compatibilidad con V1 al revés, al menos en el corto plazo)?
Por lo que yo veo que tiene un par de opciones de soporte ...
- gota para V1 inmediatamente y lidiar con las consecuencias (peor solución posible)
- Se comienza reemplazando el to_ [formato ] methods (estoy bastante seguro de que harías esto con as_ [format] pero eso está al lado del punto) para incluir un nuevo atributo ...
name_2
- esto parece igualmente tonto - Implementa algún tipo de clase proxy que sea responsable de exponer solo los métodos que estamos buscando
- Let vistas manejan la creación de algún tipo de hash que los controladores y versionados llaman
to[format]
en ...
tres y cuatro son los únicos que realmente hace que se me ocurre ningún tipo de sentido ... Tres vería algo como:
# model
class Api::V1::Product < Struct.new(:product)
def to_json
attributes.to_json
end
def to_xml
attributes.to_xml
end
private
def attributes
{:name => product.name} # add all the attributes you want to expose
end
end
# Controller
class Api::V1::ProductsController < V1Controller
respond_to :json, :xml
def show
respond_with @product = Api::V1::Product.new(Product.find(params[:id]))
end
end
¿Qué han hecho otras personas en el pasado?
Esta es una solución realmente buena, algo en lo que no había pensado ... – Coop