Hello and happy Friday!
Continuing with my learning on the topic of APIs in Ruby, I’ve been reading a book entitled Rails 3 in Action by Yehuda Katz and Ryan Bigg. If you’re using Rails 4, they also have a new release under the same title which also features Steve Klabnik as an author, and is slated to be available at the end of March according to Amazon.
Today, I’m going to cover what I’ve read so far from chapter 13 “Designing an API”.
What is an API
An application programming interface makes allowances and also specifies how some software components should interact with one another.
An API is usually related to a software library (also referred to as a client), but can also be an implementation of a protocol or used in the context of web development typically defined as a set of HTTP requests and a definition of the structure of response messages.
Step 1: TDD
We use the
rack-test gem to test what our API’s URLs are doing. To set this up, we can add structure to our
spec folder. We can add an
apis folder (keeping it plural in the event that our application will use more than one api in the future), and inside of this
apis folder we can add a
v1 folder to house the tests for version 1 of our API.
Inside of the
v1 folder we can create a spec file named after our api that will have the similar structure of
api_name_spec.rb, and place the following inside of the file.
We’re passing in an option of
type: :api into our
describe block in order to have the
Rack::Test::Methods module loaded into each test automatically, instead of having to manually enter this into all our test files.
Next we need to create another sub-folder inside of our
spec folder. When we’re done, our subfolder tree should look like
spec/support/api/helper.rb, and contain the following code:
And in our
spec_helper.rb file inside of the
Rspec.configure block we can add the following:
Now that we’ve defined our
ApiHelper module in our
/spec/support/api/helper.rb file, we can consider this included with any test marked with an API and with the
:type option passed in as we saw earlier.
And we’ve defined the
app method so that
Rack::Test::Methods knows which application to perform in.
Step 2: Create a Spec
In our file
spec/apis/v1/your_api_name_spec.rb we can create a user to use with our request to the API. Lets follow the book and good TDD practice by using
let to set up a user 1 time to be used in more than one place.
We also need to setup Devise to include the
token_authenticatable module so we can authenticate API requests from users by a token they will provide with each request. The authentication token is an identifier that will allow us to know what API features to present to our users.
We can head on over to the User model and change our Devise attributes to the following:
Follow this up with a migration adding the string
authentication_token to our users table so we can actually store this token identifier. Once we’ve added this database field, we can run
rake db:migrate to create the column in our database, and
rake db:test:prepare to migrate our test environment’s database.
We need to add a callback to our User model so that authentication tokens are generated when a user is created, or for when users are updated but don’t have a token. We can do this with a before filter like so:
With this callback to create a User token all setup, let us finish out the spec.
get method on line: 16 makes a GET request with the provided URL, and is provided by the module
Rack::Test::Methods. Since we want to keep our code dry we’re placing the URL with
let so we don’t have to re-define it several times in future tests.
Step 3: Define routes to the API
I found this blog post from Collective Idea, an agile software-team that does Rails (among other things) located in Holland MI. The post is very informative about the how and why of name spacing an API, versioning, creating a subdomain to help us load balance traffic at the DNS level and using
respond_to to handle JSON requests.
Here’s a quote from the post:
API versioning can be controversial1, but if you want to add version info into your URLs, simply add another namespace to your routes:
namespace :api do
namespace :v1 do
Now your version 1 API is at URLs starting with /api/v1/ and your controller would be in a v1 folder with the added v1 module.
class API::V1::PeopleController < ApplicationController
You could now support multiple versions at the same time, just make sure you have a very good test suite so you don’t break v1 when you go to v2.
So assuming that we want to version our api we can define our routes like so:
This gives us pretty URL names and helps keep our now name spaced API clean and well organized.
This is pretty much what I’ve been reading and learning to comprehend over the past day or so. I’m looking forward to next week, as I’ll have an AirPair with Adam Cuppy on using a 3rd party API in my current project.
Stay tuned, and have a great weekend!
Categories: Ruby on rails