I’ve begun experimenting with Hypermedia APIs a bit more seriously, trying to come up with a good infrastructure for the next version of the Artsy API. It might even be a public one, but I am not making any promises right now. I’ve played with serialization and attempted to use ActiveModel::Serializers with the grape-activemodel_serializers gem and HAL with Roar. It turned out that we do need a little bit of help with Roar, so I released a new gem called grape-roar, which enables using Grape’s present keyword.
Check out an example application deployed at grape-with-roar.herokuapp.com, source code in https://github.com/dblock/grape-with-roar.
First, swap the JSON formatter for Grape::Formatter::Roar. It’s implementation is almost identical to the default JSON formatter, except that it passes env along to the to_json call.
module Acme
module Api
class RootEndpoint < Grape::API
prefix 'api'
format :json
formatter :json, Grape::Formatter::Roar
end
end
end
Implement a presenter. It will typically have a number of :properties. Include Grape::Roar::Representer to use _present _in your API.
module Acme
module Api
module Presenters
module SplinePresenter
include Roar::Representer::JSON::HAL
include Roar::Representer::Feature::Hypermedia
include Grape::Roar::Representer
property :uuid
property :reticulated
link :self do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/splines/#{uuid}"
end
end
end
end
end
You can now present an entity in your API implementation.
module Acme
module Api
class SplinesEndpoint < Grape::API
namespace :splines do
desc 'Get a spline.'
params do
requires :id, type: String, desc: 'Spline id.'
end
get ':id' do
spline = Acme::Models::Spline.find(params[:id])
present spline, with: Acme::Api::Presenters::SplinePresenter
end
end
end
end
end
Representing collections is similar, check out https://github.com/dblock/grape-with-roar for a complete example with bonus pagination support.
I’d love it if someone could contribute a POST/PUT example.