Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write rails route to map versioned API with major and minor version in path like /api/v1.2/users/1234

I've read this Best practices for API versioning?. And I agree with putting the version in url path rather than in HTTP header.

In order to implement this, I have a namespaced controller like this:

class Api::V1::UsersController < Api::BaseController
  def show
    ...
  end
end

And the route are:

current_api_routes = lambda do
  resource :users
end

namespace :api do
  namespace :v1, &current_api_routes
end

Then rake routes I can get routes like this:

api_v1_user GET    /api/v1/users/:id(.:format)                       api/v1/users#show
...

I want that version v1.2 goes to controller of v1. Then I can get minor version number in controller like this:

class Api::V1::UsersController < Api::BaseController
  def show
    minor_version = params[:minor_version] # minor_version = 2
    ...
  end
end

Is there a way to achieve this?

like image 545
ryancheung Avatar asked Jan 25 '13 01:01

ryancheung


1 Answers

We are using minor API versioning for small but possibly breaking changes (like allowing null values for an attribute that previously wouldn't be allowed to be so).

# config/routes.rb
My::Application.routes.draw do
  namespace :api do
    scope "v:api_version", module: "v1", as: "v1", constraints: { api_version: /1(\.[0123]?)/ } do
      resources :users
    end
  end
end

# app/controllers/api/application_controller.rb
class API::ApplicationController < ActionController::Base
  private
  def api_version
    @api_version ||= begin
      major, minor = params[:api_version].split('.', 2).map(&:to_i)
      OpenStruct.new(major: major, minor: minor || 0)
    end
  end
end

# app/controllers/api/v1/users_controller.rb
class API::V1::UsersController < API::ApplicationController
  def show
    # ...
    something_more if api_version.minor >= 2
  end
end
like image 51
wvengen Avatar answered Oct 15 '22 07:10

wvengen