I’ve seen two common API versioning strategies in the wild. The first is to use a single API version and gradually deprecate methods. This usually means introducing new API routes, while retiring old ones, and representing the same objects in multiple, versioned, formats. Fast forward a few years and you are likely to inherit a significant amount of technical debt. The second strategy involves making a clean cut, leaving the version one of the API alone and building a fresh, new, API version two.
Starting with the Grape 0.6.0 you can have a third alternative: building a new API version incrementally on top of a previous one. There’re no hacks involved. Consider the following trivial API.
Define the next API version.
At this point we want v1 to be identical to v2, except for the root method. We’ll start by allowing v1 to respond to both v1 and v2 requests.
Mount v2 before v1. The default versioning behavior is to cascade the request to the next Rack middleware.
Try it on my demo project in https://github.com/dblock/grape-on-rack-v1-inside-v2.
By default we get the root of v2 and the only_in_v1 method implemented on v1.
curl https://localhost:9292/
{"version":"v2"}
curl https://localhost:9292/only_in_v1
{"only_in_v1":"true"}
With version two, we get the same thing.
curl https://localhost:9292 -H "Accept:application/vnd.acme-v2+json"
{"version":"v2"}
curl https://localhost:9292/only_in_v1 -H "Accept:application/vnd.acme-v2+json"
{"only_in_v1":"true"}
With version 1 we get the old behavior.
curl https://localhost:9292 -H "Accept:application/vnd.acme-v1+json"
{"version":"v1"}
curl https://localhost:9292/only_in_v1 -H "Accept:application/vnd.acme-v1+json"
{"only_in_v1":"true"}
The only fix needed in Grape for this was to enable multiple versions specified with version, committed in 2be499c51.
This came up on the Grape mailing list.