Skip to content

A pragmatic approach of api versioning

fabrik42 edited this page May 14, 2011 · 2 revisions

A pragmatic approach of API versioning

In case you need to provide different versions of the API, this can be done easily using different API templates:

class User < ActiveRecord::Base

  acts_as_api

  api_accessible :v1_public do |template|
    template.add :first_name
    template.add :age
  end

  # offer an additional avatar field in the public template of v2 
  api_accessible :v2_public, :extends => :v1_public do |template|
    template.add :avatar
  end

  api_accessible :v1_private do |template|
    template.add :first_name
    template.add :last_name
    template.add :age
  end

  # offer an additional avatar and birthday field in the public template of v2 
  api_accessible :v2_private, :extends => :v1_private do |template|
    template.add :avatar
    template.add :birthday
  end
end

For an easy composition of the template name you can use a helper method like this, e.g. in your ApplicationHelper:

def api_template(version = :v2, template = :public)
  "#{version.to_s}_#{template.to_s}".to_sym
end

Which would look like this in your controllers. You can determine the API version using params[:version].

class UsersController < ApplicationController

  # renders the :v2_public template by default
  def show
    @user    = User.find(params[:id])
    template = api_template(params[:version])

    respond_to do |format|
      format.html # show.html.erb
      format.xml   { render_for_api template, :xml  => @user }
      format.json  { render_for_api template, :json => @user }
    end
  end
  
  # renders the :v2_private template by default
  def profile
    @user    = User.find(params[:id])
    template = api_template(params[:version], :private)

    respond_to do |format|
      format.html # show.html.erb
      format.xml   { render_for_api template, :xml  => @user }
      format.json  { render_for_api template, :json => @user }
    end
  end  

end