Skip to content

Instantly share code, notes, and snippets.

@dblock
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dblock/5aa4050ee91681d6df99 to your computer and use it in GitHub Desktop.
Save dblock/5aa4050ee91681d6df99 to your computer and use it in GitHub Desktop.
Implement a Hypermedia API with Grape + Roar

Create Gemfile

source 'http://rubygems.org'

gem 'grape'
gem 'grape-roar'

Run bundle install.

Create an API Root

Create api.rb.

class Api < Grape::API
  format :json

  desc 'Root of the Hypermedia API.'
  get do
    { foo: 'bar' }
  end
end

Create config.ru.

$LOAD_PATH.unshift(File.dirname(__FILE__))

require 'rubygems'
require 'bundler/setup'

Bundler.require :default

require 'api'

run Api

Run rackup, browse to http://localhost:9292, see the API.

Create a Model

Add activemodel to Gemfile.

gem 'activemodel', require: 'active_model'

Create models/spline.rb.

class Spline
  include ActiveModel::Model

  attr_accessor :uuid
  attr_accessor :reticulated

  def initialize(attrs = { reticulated: [true, false].sample })
    super(attrs)
    @uuid ||= SecureRandom.uuid
    @reticulated = !!attrs[:reticulated]
  end
end

Return a Spline in the API

  resource :splines do
    desc 'Return a spline.'
    get ':uuid' do
      Spline.new(uuid: params[:uuid])
    end
  end

Make a presenter.

module SplinePresenter
  include Roar::Representer::JSON::HAL
  include Roar::Representer::Feature::Hypermedia
  include Grape::Roar::Representer

  property :uuid
  property :reticulated

  link :self do
    "http://localhost:9292/splines/#{uuid}"
  end
end

Require JSON+HAL.

require 'roar/representer'
require 'roar/representer/json'
require 'roar/representer/json/hal'

require 'presenters/spline_presenter'

Present the spline.

present Spine.new(uuid: params[:uuid]), with: SplinePresenter

See it at http://localhost:9292/splines/123.

Return a Collection of Splines

Create a presenters/splines_presenter.rb.

module SplinesPresenter
  include Grape::Roar::Representer
  include Roar::Representer::JSON::HAL
  include Roar::Representer::Feature::Hypermedia

  collection :to_a, extend: SplinePresenter, as: :splines, embedded: true
end

Require it.

require 'presenters/splines_presenter'

Present splines.

desc 'Return a few splines.'
get do
  present 5.times.map { Spline.new }, with: SplinesPresenter
end

Add a Root Presenter

Create presenters/root_presenter.rb.

module RootPresenter
  include Roar::Representer::JSON::HAL
  include Roar::Representer::Feature::Hypermedia
  include Grape::Roar::Representer

  link :self do
    "http://localhost:9292"
  end

  link :splines do
    "http://localhost:9292/splines"
  end

  link :spline do |opts|
    {
      href: "http://localhost:9292/splines/{uuid}",
      templated: true
    }
  end
end

Require it.

require 'presenters/root_presenter'

Present it.

desc 'Root of the Hypermedia API.'
get do
  present self, with: RootPresenter
end

Try It

require 'hyperclient'

client = Hyperclient.new('http://localhost:9292')

client.splines.count

client.splines.each do |spline|
    puts "Spline #{spline.uuid} is #{spline.reticulated ? 'reticulated' : 'not reticulated'}."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment