This is a blog of
AmberBit
- a Ruby on Rails web development company.
Hire us
for your project!

Building and documenting API in Rails

2014-2-19

These are really exciting times for web developers.
New JavaScript frameworks emerge constantly, completely changing the way
we think about building web applications.
With libraries such as AngularJS, Ember.js or Backbone.js, the server is
no longer responsible for generating complete pages. Its
role is often reduced to serving as a backend for client-side
application.
This approach has many advantages. To name a few:

it allows better separation between presentation and business logic

better performance for the user - instead of reloading the whole
page, only parts that need to change are replaced

reduced resources usage - fetching only small chunks of data instead of
rendering whole pages, as well as pulling large parts of business
logic into web browser, can be a huge relief for your web server and
as a result - for your pocket

it can save you substantial amount of work if you’re creating multiple clients,
for example website and native mobile clients for iOS, Android etc.
A good, well-defined API can be reused for all these purposes.

You might have doubts if large, full-featured framework like Ruby on Rails
is a right tool for building such backend. Indeed, it might look like an overkill.
However, I believe it is not. With just a little bit of configuration and some useful
gems, we can disable the parts that we don’t need and still use all the Rails’
goodness we’re used to. And, while it might not be obvious at first
sight, many Rails features are applicable to API applications:

routing - resourceful routes lie at the heart of a good REST API.
Rails router makes it super easy co create them effortlessly

easy testing - testing is vital part of software development, and API
applications are no different.

rich library of third-party plugins - no matter what functionality
your application needs, chances are that someone already implemented it

convenient defaults for development mode

logging

and much more

In this article we’ll have a look at creating an API using Ruby on
Rails. We’ll try to cover some of the most common issues one can encounter when
developing such application. For illustrative purposes we’ll use a
sample application, which allows tracking projects user participates in.

Getting Started

When creating an API application we don’t need all the features that
Rails provides out of the box. For example, we’re not interested in
generating templates on the server.
Picking the features needed for building an API is trivial when using
Rails::API gem.

Alternatively, if you’re creating your application from scratch, you can
install rails-api as a standalone gem

$ gem install rails-api

and generate new project using

$ rails-api new my_api

Rails::API includes sensible set of middlewares enabled by default. It’s
possible to add the ones that are inactive. For example to add Session
Management, you simply need to add following line in config:

Versioning

To be of any value, API must remain stable and consistent. If you
introduce any changes to the routing, parameters passed to the API or
response format, clients using the API might break.
The above statement is especially true for publicly available APIs,
which can be used by large number of third-party clients.
On the other hand, evolution of software is completely natural and
inevitable. How can we reconcile these contradictions? API versioning to
the rescue!
Thanks to versioning, you can release new, improved API, without
cutting off clients using the old one.
Let’s set up routes for our versioned API:
config/routes.rb

MyApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :user
...
end
end
end

If at some point in the future we decide to introduce new version of our
API, we can simply create new namespace for it, like this:

MyApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :user
...
end
namespace :v2 do
resources :user
...
end
end
end

and create controllers structure analogous to the existing one.

Rendering Response

There are many formats, in which communication with the API can be
performed. The most popular choices are XML and JSON. For our sample
application we will use the latter exclusively.
JSON, or JavaScript Object Notation, has its origins in JavaScript, but
is widely supported by other programming languages, including Ruby.
JSON’s main advantage over XML is simpler syntax, which makes it easier to
read by human and faster(both in parsing and - due to smaller size -
transmission over the Internet).
Thanks to built-in support for JSON, creating response in this format in
Ruby on Rails is a breeze:

This way works perfectly fine for simple responses. However, if there’s
more data you would like to return, you controller might get pretty fat.
For these cases, we can use one of available DSLs.
The one I find most convenient is Jbuilder,
enabled by default in Rails 4. If you’d like to use it with older
version of Rails, you might need to uncomment it in the Gemfile (or add
it altogether, for really old versions):

# To use Jbuilder templates for JSON
gem 'jbuilder'

It helps you by adding support for loops and conditional statements, as
well as partials. Let’s see all that in action!
Jbuilder files are treated like a regular template files: you put them
in app/views directory. For example, let’s have a look at template for
single project:
app/views/api/v1/projects/show.json.jbuilder

Of course, Jbuilder is not the only option you have. I suggest also
having a look at RABL.

Response from an API is not complete without correct HTTP response code.
To set status code in you controller, just pass :status key to
render method, like this:

render json: {message: 'Resource not found'}, status: 404

You can also use symbols instead of numbers:

render json: {message: 'Resource not found'}, status: :not_found

Full list of status codes can be found here, but you’re
most likely to use only limited subset of them:

200 - :ok

204 - :no_content

400 - :bad_request

403 - :forbidden

401 - :unauthorized

404 - :not_found

410 - :gone

422 - :unprocessable_entity

500 - :internal_server_error

One last improvement to the way we handle response formats is setting
JSON as the default. We can do so in config/routes.rb file:

namespace :api, defaults: {format: 'json'} do
namespace :v1 do
...
end
end

This way, when sending request to

http://www.example.com/api/v1/projects.json

we can omit the format:

http://www.example.com/api/v1/projects

Authentication

An API is a gateway to your application. In most cases you don’t want to
allow everyone to access, edit and remove data. You need to make sure that only
authorized users will be able to alter it.
One way to secure your API is by Access Tokens.
We’ll create a separate model, called ApiKey, to store token. The
token itself will consist of 32 hexadecimal characters. Let’s have a
look at ApiKey class:

The class is very simple. It has a callback method generate_token,
which creates unique string of hexadecimal characters when the class is instantiated.
Next, let’s make sure that every user will be assigned his api key upon registration

We support passing acces token both as a header and parameters.
To support header authentication, we need to include
ActionController::HttpAuthentication::Token::ControllerMethods module,
which is disabled by Rails::API by default.
Now, we need to make sure that the token will be checked with each call
to the API. We’ll add before_filter to our controllers:

before_filter :restrict_access

Testing

When testing an API, you should test both response body and
HTTP status codes.
An example of test that checks both:
spec/api/tasks_api_spec.rb

The syntax for formatting your comments is very simple. Here are some
basic rules, that you’ll find most useful:

lines starting with = are headers. The number of = characters
defines the level of heading, so

= Header

will result in following HTML:

<h1>Header</h1>

, while

== Header

will give you

<h3>Header</h3>

hyphen and asterisk are items of unordered list

digit or a letter followed by a dot are itams of ordered list

for labelled list, wrap labels in square brackets or append two
colons to them

[label] description
another:: description 2

to alter text style, use bold, italics or +monospace+

any lines starting with larger indentation than the current margin
are treated as verbatim text. It’s great for embedding code snippets
with syntax highlighting inside the documentation

It’s also possible to use different markup format, than the default
RDoc::Markup. RDoc has built in support for markdown, rd and tomdoc.

More in-depth reference for Rdoc syntax, as well as another markup
formats can be found in project documentation

To generate documentation, run rdoc command in project main directory.
It will store html files containing newly created documentation inside
doc directory. You can also define index page for a documentation. In
our case, the command to generate documentation will be

rdoc --main README.md

Summary

We covered basic steps required to build your own REST API with Ruby
on Rails. It was by no means comprehensive guide, but it should be enough to get
you started on yout way to mastering the art of building great APIs.