Responders::ApiResponder
ApiResponder
simplifies version dependent rendering of API resources using a custom responder and a mixin for decorators or models (decorators are recommended).
Installation
Add this line to your application's Gemfile:
gem 'api-responder'
And then execute:
$ bundle
Or install it yourself as:
$ gem install api-responder
Usage
Add Responders::ApiResponder
to your responder chain:
class AppResponder < Responder
include Responders::ApiResponder
end
class MyController < ApplicationController
self.responder = AppResponder
end
Or use it with plataformatec/responders:
class MyController < ApplicationController
responders Responders::ApiResponder
end
This will add an API version parameter to the options hash for formatting methods like as_json
. You can override the formatting methods or just include ApiResponder::Formattable
:
class MyModel
include ApiResponder::Formattable
api_formats :xml
def as_api_v1
{
id: id,
first_name: name.split.first
last_name: name.split.last
}
end
def as_api_v2
as_api_v1.merge name: "#{first_name} #{last_name}"
end
end
This will add a handler for XML. You can specify any format your want. ApiResponder::Formattable
will override the to_{format}
(e.g. to_xml
) method to call to_{format}
on the API specific hash. JSON is supported via as_json
by default.
The only included method to detect API version is matching the URL path /api/v(\d+)
. Or you can add an api_version
method to your controller:
class MyController < ApplicationController
responders Responders::ApiResponder
def api_version
return $1 if request.headers["Accept"] =~ /vnd\.myapp.v(\d+)/
end
end
I recommend using ApiResponder
in combination with jgraichen/decorate-responder and the decorator pattern (like draper):
class User < ActiveRecord::Base
attr_accessible :id, :first_name, :last_name
end
class UserDecorator < Draper::Decorator
include ApiResponder::Formattable
decorates :user
api_formats :msgpack
def name
"#{first_name} #{last_name}"
end
def as_api_v1
{
id: model.id,
created_at: model.created_at.utc.iso8601,
name: name
}
end
end
class UsersController < ApplicationController
responders Responders::ApiResponder,
Responders::DecorateResponder
respond_to :json, :xml, :msgpack
rescue_from ApiResponder::Formattable::UnsupportedVersion do
head :not_acceptable
end
def index
respond_with User.scoped
end
def api_version
return $1 if request.headers["Accept"] =~ /vnd\.myapp.v(\d+)/
end
end
When ApiResponder::Formattable
receives nil as API version or the resource does not have a matching as_api_v
method an UnsupportedVersion
error will be raised. You can catch that exception and for example return a 406
status code:
rescue_from ApiResponder::Formattable::UnsupportedVersion do
head :not_acceptable
end
Check out jgraichen/paginate-responder for automagic pagination support including HTTP Link headers.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Write tests for your feature
- Add your feature
- Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
License
Copyright (c) 2013 Jan Graichen