我目前正在为新网站设计版本化 API。我了解如何命名路由,但我坚持在模型中实现版本化方法的最佳方式。
下面的代码示例使用的是 rails 框架,但大多数 web 框架之间的事情原理应该是一致的。
路线目前看起来像:
MyApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :products, :only => [:index, :show]
end
end
end
和控制器:
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
所以很明显,我们只是在这里公开了 Product 上可用的属性,如果你只需要一个版本的 API,这个解决方案就很好用。当您想要发布 V2 并且 V2 需要重新实现产品名称的显示方式时会发生什么(同时保持与 V1 的向后兼容性 - 至少在短期内)?
据我所知,你有几个选择......
- 立即放弃对 V1 的支持并处理后果(可能的最坏解决方案)
- 您开始覆盖 to_[format] 方法(我很确定您使用 as_[format] 执行此操作,但这是题外话)以包含一个新属性...-
name_2
这似乎同样愚蠢 - 实现某种代理类,它只负责公开我们所追求的方法
- 让视图处理创建某种散列,版本化控制器并调用
to[format]
...
三个和四个是我真正认为有意义的唯一一个......三个看起来像:
# 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
其他人过去做了什么?