Andy Jeffries - Taekwondo, Rails and Go

Using Flexirest to Access an API

Introduction

user

Andy Jeffries


Using Flexirest to Access an API

Posted by Andy Jeffries on .
Featured

Using Flexirest to Access an API

Posted by Andy Jeffries on .

While contracting at Which? Ltd, I wrote a Ruby Gem to allow Ruby Developers to easily interact with REST-based services called ActiveRestClient. Sure, there are other libraries out there to do this, but I’ve felt for a while there was nothing that was as easy as ActiveRecord. ActiveResource was a nice idea, but it’s really a pain to work with unless you’re communicating with another Rails server using standard RESTful routes.

After a few months of discussion with Which’s legal department (with the full backing of the CTO and the Head of Software Engineering), we managed to agree to release ActiveRestClient as an open source gem under the MIT licence in February 2014. Unfortunately, since that seems to have been abandoned after I left, I forked it to be called Flexirest.

Important: This blog post is the opinion/writing of Andy Jeffries and in no respects represents the opinion of Which? Ltd

Background

There’s full documentation on the Flexirest GitHub page, but as a simple explanation, I thought I’d show how to interact with an API. Let’s quickly build a client for GitHub’s v3 API.

So, on my fictional website I want to display a count of the number of people suscribing to the repository (Watching in GitHub terms) Flexirest. The API for this is very simple, but it requires authentication. So before we start, we’ll need to create a Personal Access Token. GitHub has great instructions on how to do this.

For the remainder of this example, I’ll use 1234567890 as the token. You should generate your own.

According to the GitHub Documentation you can pass this token as a GET parameter called access_token.

The Task

Simple Model Setup

OK, so the first step is to create a model file called something like app/models/git_hub_subscriber.rb (I’m assuming the reader is familiar with Rails development, if not, you can create this as just a general class in the load path of your project, this example won’t need Rails to work). We’ll start off with the very barebones of an Flexirest model:

class GitHubSubscriber < Flexirest::Base

end  

The first thing to do for the API class is to define the base URL. This can be done on a per class basis or globally using Flexirest::Base.base_url = “https://api.github.com", but we’ll do it on just this class:

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com"
end  

The next step is to map the request as described by GitHub.

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com" 
  get :all, '/repos/:owner/:repo/subscribers'
end  

I’ve intentionally left the symbol tokens in the URL because Flexirest uses this convention to mark parameters too.

We need to add in our access_token. We’ll do this in a safe way by defining a constant somewhere in our application (config/application.rb reading from an ENV variable is probably a good place). Let’s set the constant somewhere first:

GITHUB_TOKEN = 1234567890  

Then I’ll use it in a really simple way, by simply setting it as a default GET parameter value:

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com"
  get :all, '/repos/:owner/:repo/subscribers', defaults:{access_token:GITHUB_TOKEN} 
end  

There’s a couple of parts of the GitHub API documentation that’s important that we implement before we can call any API.

We must send an Accept header with a value of application/vnd.github.v3+json. Flexirest allows tweaking the outgoing request in any way using before_request filters:

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com" 
  before_request do |name, request| 
    request.headers["Accept"] = "application/vnd.github.v3+json"
  end
  get :all, '/repos/:owner/:repo/subscribers', defaults:{access_token:GITHUB_TOKEN} 
end  

User Agent

We also need to send a user agent. Given that we already have a before_request block altering headers, it’s really easy to add that in:

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com"
  before_request do |name, request| 
    request.headers["Accept"] = "application/vnd.github.v3+json" 
    request.headers["User-Agent"] = "AndyJeffries/1.0" 
  end
  get :all, '/repos/:owner/:repo/subscribers', defaults:{access_token:GITHUB_TOKEN}
end  

At this point, it’s already usable:

irb > GitHubSubscriber.all(owner:"andyjeffries", repo:"flexirest").count  
 => 33

We can make that owner and repo the default for our site:

class GitHubSubscriber < Flexirest::Base  
  base_url "https://api.github.com" 
  before_request do |name, request| 
    request.headers["Accept"] = "application/vnd.github.v3+json" 
    request.headers["User-Agent"] = "AndyJeffries/1.0" 
  end 
  get :all, '/repos/:owner/:repo/subscribers', defaults:{ access_token:GITHUB_TOKEN, owner:"andyjeffries", repo:"flexirest"}
end  

Of course you can also interact more fully with the API, each object in the list has normal methods corresponding with the API’s response, for example:

GitHubSubscriber.all(owner:"andyjeffries", repo:"flexirest").each do |subscriber|  
  puts subscriber.login
end  
user

Andy Jeffries