How to Version API in Rails: Simple Guide with Examples
In Rails, you version an API by organizing your controllers into versioned namespaces using
module and namespace in routes. You can also use request headers to route requests to the correct API version, keeping your app clean and backward compatible.Syntax
API versioning in Rails typically uses namespace in the config/routes.rb file to separate versions. Controllers are placed inside matching modules. This keeps versions isolated and easy to manage.
namespace :v1 do- defines version 1 routesmodule Api::V1- groups controllers for version 1- Routes inside the namespace respond to URLs like
/api/v1/...
ruby
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :posts
end
end
end
module Api
module V1
class PostsController < ApplicationController
def index
render json: { message: 'API v1 posts index' }
end
end
end
endExample
This example shows a simple API with two versions: v1 and v2. Each version has its own PostsController with different responses. The routes use namespaces to separate versions.
ruby
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :posts, only: [:index]
end
namespace :v2 do
resources :posts, only: [:index]
end
end
end
module Api
module V1
class PostsController < ApplicationController
def index
render json: { version: 'v1', posts: ['Post 1', 'Post 2'] }
end
end
end
end
module Api
module V2
class PostsController < ApplicationController
def index
render json: { version: 'v2', posts: ['New Post A', 'New Post B'] }
end
end
end
endCommon Pitfalls
Common mistakes when versioning APIs in Rails include:
- Not isolating controllers by version, causing code conflicts.
- Forgetting to update routes to include the version namespace.
- Hardcoding version in URLs without flexibility for header-based versioning.
- Mixing version logic inside controllers instead of separate modules.
Using only URL versioning can limit flexibility; consider header-based versioning for cleaner URLs.
ruby
## Wrong: Single controller handling multiple versions class PostsController < ApplicationController def index if request.headers['Accept']&.include?('application/vnd.myapp.v2+json') render json: { version: 'v2', posts: ['New Post A'] } else render json: { version: 'v1', posts: ['Post 1'] } end end end ## Right: Separate controllers per version module Api module V1 class PostsController < ApplicationController def index render json: { version: 'v1', posts: ['Post 1'] } end end end end module Api module V2 class PostsController < ApplicationController def index render json: { version: 'v2', posts: ['New Post A'] } end end end end
Quick Reference
Tips for API versioning in Rails:
- Use
namespacein routes for clear version separation. - Place controllers in matching modules like
Api::V1andApi::V2. - Consider header-based versioning for cleaner URLs and better client flexibility.
- Keep versions isolated to avoid breaking changes.
- Document your API versions clearly for users.
Key Takeaways
Use route namespaces and controller modules to separate API versions cleanly.
Keep each API version isolated to avoid conflicts and ease maintenance.
Consider header-based versioning for flexible and clean API URLs.
Always update routes and controllers together when adding new versions.
Document API versions clearly to help clients use the correct version.