Make a painless web API in Ruby
Sure, you can implement an API many ways, including some very painful ones involving nothing but base Rails functionality.
But why do any of that when you can enjoy crafting your API?
Grape provides an easy-to-write, easy-to-read DSL for creating non-REST, REST-ish, or REST APIs, even including painless versioning. If you're using Ruby for your main application, your Grape API can easily be mounted alongside or inside any Rack application (including Rails apps).
Need a useless API to return the epoch time? Too easy:
module TickTock
class API < Grape::API
version 'v1', using: :path
format :json
get "epoch" do
Time.now.to_i
end
end
end
Mounted within Rails, it's even a snap to puke out your ActiveRecord objects:
class QuoteAPI < Grape::API
# ...
resource :quotes do
get :random do
Quote.find_random
end
end
# ...
end
Et voila, JSON:
{
"id": "42",
"uid": "92cfceb39d57d914ed8b14d0e37643de0797ae56",
"text": "There is nothing to fear but bears on skates.",
"author": "Oscar Wilde",
"truthiness": "true",
"year": "2013"
}
"But wait," you may be saying, "my object model is full of data I don't want to expose!" This too is easy to deal with (in several flavors, no less). Grape offers an optional plugin to define Entities—that is, the data you want to expose, and (optionally) any transmogrification it needs to undergo to be presentable. Let's say we don't want to reveal that some quotes are fake, or the fact they may have been written a century after the supposed author died. And let's say we've standardized on using the UID for all API access.
We can simply embed an entity definition in our model class:
class Quote < ActiveRecord::Base
# ...
class Entity < Grape::Entity
expose :uid, :text, :author
end
end
And blammo:
{
"uid": "92cfceb39d57d914ed8b14d0e37643de0797ae56",
"text": "There is nothing to fear but bears on skates.",
"author": "Oscar Wilde"
}
Not HATEOASy enough for your tastes? It's easy enough to implement HATEOAS ideas using Grape alone, but you can also work smarter and extend its capabilities with Roar or other hypermedia presenters.
Grape has a simple DSL, wide compatibility with add-ons, and is easily extensible. Give it a shot for your next API project; you may find building an awesome, forward-and-backward-compatible API is much easier than you ever expected.
Written by Colin Mattson
Related protips
2 Responses
Grape is good. Grape in combination with Swagger is even better. To generate automatic docs. https://github.com/tim-vandecasteele/grape-swagger
In my solution I have to do the following:
users = CloudUser.all
present :data, users, :with => CloudUser::Entity
After defining:
class CloudUser < ActiveRecord::Base
self.primary_key = :username
has_many :configurations, :class_name => 'Configuration'
has_many :favorites, :class_name => 'Favorite', :foreign_key => :username
class Entity < Grape::Entity
expose :username, :email, :first_name, :last_name
end
end
So it wasn't as easy as just defining a class Entity for me.