CITguy

DIY Coder

© 2014. All rights reserved.

« Back

How I Version APIs

Resources


Sick of having API versioned paths in your rails app? Try using Action Pack Variants instead.

The following is a simple example on how to implement this functionality with a Rails 4.1 application.

Set up your routes

Configure your routes as you would for a JSON endpoint.

1 # config/routes.rb
2 Rails.application.routes.draw do
3   scope(format: :json) do
4     get :hello, controller: :sandbox
5   end
6 end

Define your custom Vendor MIME type

Try to use a definition that has very little chance of interfering with other possible API services. Here, I use the java naming notation (com.mydomain.api) to associate the MIME type specifically with my domain.

1 # config/initializers/mime_types.rb
2 # Define a custom Vendor MIME type
3 Mime::Type.register "application/com.mydomain.api-v1+json", :v1json

request.variant

It is now a simple matter of setting the request.variant to the proper variant name for the new MIME format (lines 6-8).

 1 # app/controllers/sandbox_controller.rb
 2 class SandboxController < ApplicationController
 3   def hello
 4     respond_to do |format|
 5       format.json # hello.jbuilder
 6       format.v1json do
 7         request.variant = :v1 # hello+v1.jbuilder
 8       end
 9     end
10   end
11 end

Define your variant views

Since we used :v1 as our variant name, we will need a hello+v1.jbuilder variant to go along with it.

1 # app/views/sandbox/hello.jbuilder
2 json.hello "from default json"
3 
4 # app/views/sandbox/hello+v1.jbuilder
5 json.hello "from v1 json variant"

Setup your requests

Finally, your requests will need to send the proper Content-Type header to request the correct response variant.

1 // GET [Content-Type:"application/json"] /sandbox/hello
2 { "hello":"from default json" }
3 
4 // GET [Content-Type:"application/com.mydomain.api-v1+json"] /sandbox/hello
5 { "hello":"from v1 json variant" }

Benefits

A huge benefit of doing this way would be the lack of needing to maintain multiple nested, versioned routes and their associated controllers and views. This reduces your code footprint as well as routing complexity. Simply modify your output based on the versioned MIME requested.

Happy Coding!