Project Ramon

A learning journey from a Ruby noob perspective

API Design in Ruby (pt. 2)

api3_header_img

Hello and welcome to my blog!

Over the past week and a half, I’ve been learning about API’s. Today’s post will be a continuation of the first book I’ve read on the topic titled: Rails 3 in Action. I’ve just had two AirPairs this week, and I have lots more to share in the future! Lets get this started.

In my last post we covered some of the general characteristics of an API and its usage over the web. We covered how to setup our folder tree in such a way that when it becomes time to add additional APIs, the price of the addition would be low. We did this by namespacing and organizing our file structure in such a way that we can browse over our APIs by version number.

Today I’ll be covering how to serve an API as well as how to handle authenticating a user.

Serving an API

In order to define controllers for our namespace within a namespace, we need to add a base_controller to server as a base for all controllers within our version 1 folder. Here is the path that we’ve setup in the last post app/controllers/apis/v1/ and we’ll be adding the following to our v1 folder:

app/controllers/apis/v1/base_controller.rb
Inside of this file, we can place the following:

The respond_to method listed on line: 2 sets up any inheriting controller to have the ability to respond to JSON requests.

The respond_with method will return the JSON representation of Project.all when we make a JSON request to this path by calling to_json on the object. Whats really nice is that Rails knows to return JSON data automatically from any request that contains the .json root.

API Authentication

Just like we build authentication into our application in order to keep sensitive data locked away from the wrong eyes, API authentication is also used for this purpose. In an API our users will typically need an authentication_token in order to access anything through or on the API. A user’s statistics can also be tracked among other things. Using authentication, our API can also make the determination of a particular user’s appropriate level of authorization.

To start, we will need to authenticate our user making an API request, this can by done by validating for the presence of a unique authentication token. Lets make the token parameter that gets passed through with the user’s API request.

Since we may want the option of adding future API controllers, a good place to check for a user’s auth_token would be in a base controller. This way any additional controllers can inherit from the base controller file, and we can nip any semblance of redundancy in the bud.

So in Api::BaseController we can create a callback to check for a user token using a before_filter in our base_controller like so:

Next we should confirm whether or not this is working by generating another project, providing our user access to only one of these projects, and checking that the response from the API only contains data from the correct project. To pull this off, we can add an additional before to our project_spec's context block entitled 'projects viewable by this user'.

And since we’re creating a project that our user shouldn’t have access to read, we should add some coverage to ensure that our user can’t see the access denied project.

If we ran this spec, it will fail because the JSON data returned from our controller is including both projects. To get this spec from red to green we should prevent @projects from returning all projects in our controller’s index action, and instead only return the project’s that our user is authorized to read.

Lets visit our controller at app/controllers/apis/v1/projects_controller.rb and change the index action to use the for method instead of the typical all method that grabs all objects without concern.

This change to our index action, gives our failing spec a green thumbs up because now the only projects that are returned in the index action are the ones our user is allowed to read.

Now that our API is setup to find a user from their token of authentication, we need test coverage and implementation for the cases when no authentication token is present. We also need coverage for the case when a user’s token is invalid.

In my next post, I’ll be covering error reporting as a strategy to handle these cases.

Stay tuned…

Advertisements

Categories: Ruby on rails

Tags:

1 reply

Trackbacks

  1. API Design in Ruby (pt. 3) | Project Ramon

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s