Управление версиями API в веб-приложениях

В настоящее время я работаю над созданием версионного API для нового веб-сайта. Я понимаю, как создать пространство имен для маршрутов, но я застрял на том, как лучше всего реализовать версионные методы в модели.

В приведенных ниже примерах кода используется инфраструктура rails, но принцип работы должен быть согласован для большинства веб-платформ.

Маршруты в настоящее время выглядят примерно так:

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

Итак, очевидно, что мы просто раскрываем атрибуты, доступные в продукте, здесь, это решение отлично работает, если у вас будет только одна версия API. Что происходит, когда вы хотите выпустить V2, а V2 необходимо заново реализовать способ отображения названия продукта (при сохранении обратной совместимости с V1 - по крайней мере, в краткосрочной перспективе)?

Насколько я понимаю, у вас есть пара параметры ...

  1. Немедленно откажитесь от поддержки V1 и устраните последствия (наихудшее возможное решение)
  2. Вы начинаете переопределять методы to_ [формат] (я почти уверен, что вы делаете это с помощью as_ [формат], но это рядом суть), чтобы включить новый атрибут ... name_2 - это кажется столь же глупым
  3. Реализовать какой-то прокси-класс, который отвечает за предоставление только тех методов, которые мы ищем
  4. Let views обрабатывать создание какого-то хэша, который контролеры с поддержкой версий и вызывают в [формат] на ...

Три и Четыре - единственные, которые, как я могу думать, имеют хоть какой-то смысл ... Три будет выглядеть примерно так:

# 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

Чем занимались другие люди в прошлом?

6
задан Coop 23 July 2011 в 00:36
поделиться