Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant API versioning in Rails

At the moment I'm implementing versioning for our REST API in our Rails application. Is there a way this can be implemented so you only define new functionality in new versions? Say for example:

I have a Users controller and a Products controller. Products has stayed the same between V1 and V2, but Users has changed. It would be nice if we could set it up so that if I call for V2 of Products, my application knows it doesn't exist and simply uses the most recent controller version instead (in this case, V1). This would allow for us to not create a whole new set of controllers for every version; we'd only create new controllers for the specific functionality that has changed.

Below is a snippet from our Routes.rb, and admittedly I have no idea how to tackle this problem. Any help would be greatly appreciated!

namespace :api do
    scope module: :v1, constraints: ApiConstraints.new(version: 1) do
      resources :users
      resources :products
    end
    scope module: :v2, constraints: ApiConstraints.new(version: 2) do
      resources :users
    end 
end
like image 800
NSCodeCasts Avatar asked Sep 01 '12 16:09

NSCodeCasts


3 Answers

I've used the same strategy for sometime and recently changed approaches-and admittedly I'm biased because I'm also one of the authors of our new approach with VersionCake.

This approach is to only version our payloads or views, afterall views are the contract between the client and if there is a breaking contract change, then the version needs to change. In VersionCake, you can version your views like so:

app/views/products/show.v1.rabl
app/views/products/show.v2.rabl
app/views/users/show.v1.rabl

The specific feature that is important based on your question is that VersionCake will gracefully degrade to the latest supported version. Given the example above, a client requesting users/1.json for version 2 will receive the payload for users/show.v1.rabl.

All this being said, it would require adopting a new versioning approach, so it might not be the best answer, but I think it's an option worth considering.

like image 83
bencode Avatar answered Sep 29 '22 00:09

bencode


Have you looked at Grape already?

What I have done over the API's I have built is, when something changes for all of them (like authentication) I just get them all to inherit from a specific versioned api controller, as in Api::V1::BaseController and place the common behavior and controls in there.

Since changing the API usually also meant changing the representations, using a tool that generates the representations for your is also really important, there are many gems out there for this as:

  • RABL
  • Roar
  • Jbuilder
like image 37
Maurício Linhares Avatar answered Sep 29 '22 01:09

Maurício Linhares


This is what Grape is designed to do.

In addition, you have the option of mounting your API in your routes.rb file or mapping it in config.ru, bypassing the Rails stack and greatly improving the performance of the API.

like image 32
Krut Avatar answered Sep 29 '22 00:09

Krut