Introduction to APIs with Ruby and Sinatra

For the purposes of this tutorial we can think of APIs as a way of abstracting data away from any specific language or DB and into a universal format like JSON, and making it accessible over the web.

Head over to http://jsonplaceholder.typicode.com/ It hosts a sample API you can use to see an API in action.

The API contains dummy data for a fake blog. There’s links for JSON data on

Check out each of these links.

You’ll see that it returns a bunch of JSON objects with various key/value pairs This API follows the REST guidelines to organize and handle different requests and levels of detail into a hierarchical URL schema. That means we can extend the posts link above to return just post with id 3: http://jsonplaceholder.typicode.com/posts/3

That’s great, but what do I do with this data?

Now all of that is neat, but most users won’t want to just get a bunch of JSON in the browser. Let’s see what we can do to get this data into Ruby: Run these lines line by line in pry or irb.

require 'open-uri' #built-in gem to load and parse URLs
require 'json' #built-in gem to parse JSON
posts = open('http://jsonplaceholder.typicode.com/posts')
parsed_posts = JSON.parse(posts.read)
puts parsed_posts
parsed_posts.class
parsed_posts.first
parsed_posts.first.keys
parsed_posts.first["title"]

We’ve turned JSON data from an API into a Ruby hash and can now do whatever we want with it.

Notice of course that none of this code is specific to this particular API. You could throw in the URL for another API and everything but that last command would work the same. Another thing to keep in mind is that the gems used are generic built-in modules that every modern language has. The messiness of specific DBs, adapters, and languages have been abstracted away for us. APIs are platform and language agnostic. Also consider how it wouldn’t be too tough to write a Ruby gem wrapper of your own around this API.

Okay cool, but instead of just pulling data over an API what if you want to build an API server that delivers JSON data.

Well, like most things it can be as complicated as you want it to be, but setting up a simple API server is pretty easy. Let’s make a real simple Sinatra app as a proof of concept.

First let’s seed a database to work with:

require "sequel"

# create a simple SQLite DB
DB = Sequel.connect('sqlite://test.db')

# create an items table
DB.create_table :items do
  primary_key :id
  String :name
  Float :price
end

items = DB[:items]

# populate the table
items.insert(:name => 'abc', :price => rand * 100)
items.insert(:name => 'def', :price => rand * 100)
items.insert(:name => 'ghi', :price => rand * 100)

Now save the following on your computer as app.rb:

require 'sinatra'
require 'json'
require 'sequel'
db_connection = Sequel.connect('sqlite://test.db')
get '/' do
  first_item  = db_connection[:items].first
  content_type  :json
  first_item.to_json
end

Now run it with “ruby app.rb” it should start up on your local machine on port 4567. Head over to http://localhost:4567/ and check it out. You should see something like this:

{"id":1,"name":"abc","price":45.97298966228478}

Let’s try to parse that data back into Ruby. While Sinatra is still running fire up pry and run the following commands:

require 'open-uri'
require 'json'
data = open('http://localhost:4567')
parsed_data = JSON.parse(data.read)
parsed_data.class
parsed_data['name']

Now, obviously we’re not gonna need to parse our own JSON data back into Ruby, I’m just trying to show you how you’d create a API server and then how someone else could parse that data if they wanted it. Consider also that although the above Sinatra example is real simple, we could easily extend this into something quite robust if we wanted to.

Most real world examples would require things like security and authentication, so they would be a bit more complicated, but the steps I’ve outlined here are all you need to get a simple API server running.

Additional Resources