Writing an API gem: choosing the structure and the tools
The first steps are pretty simple: create a repository and initialize a simple gem in it. You can create a new gem using the command bundle gem name_of_the_gem
, and create a repository on Github. Here it is, by the way: https://github.com/Fodoj/groovehq.
First of all, I will add an opportunity to authenticate requests to GrooveHQ API, and then I will write a minimum required code for getting the list of all the tickets. Luckily, the documentation on this API is clear and detailed, that's why it's very easy to make one GET-request.
A minimal client
If you can hardly imagine what an API is and why you need it, stop for a five minutes and read our article on this subject.
I will start by writing a little class GrooveHQ::Client
, which will be responsible for delivering requests to an API. The constructor of the class will receive an access token.
# ./lib/groovehq/client.rb
module GrooveHQ
class Client
def initialize(access_token = nil)
@access_token = access_token || ENV["GROOVEHQ_ACCESS_TOKEN"]
end
end
end
How to make requests to an API
Now we need to clarify how to make requests to an API. I have never used the httparty gem for delivering requests before. My experience ends on RestClient and Faraday libraries. I don't think it matters which library to use, but in order to make the process more interesting I have chosen httparty. Especially that it has more stars on Github :)
Actually, I can't stand Faraday.
Let's add the following line to groovehq.gemspec
:
# ./groovehq.gemspec
# ...
spec.add_dependency “httparty”
# ...
and execute bundle install
. All that's left to do is link up httparty
inside of ./lib/groovehq.rb
:
# ./lib/groovehq.rb
require "httparty"
require "groovehq/version"
require "groovehq/client"
module GrooveHQ
# Your code goes here...
end
Making the first request to an API
In order to check if everything works fine, I will add the perform_request
method, which will receive a path to the API point and return a JSON with the request result. For authorization I will use an Authorization
HTTP-header, as it is stated in the API documentation. I don't like the option with the query parameter very much, as it will not work for POST-requests.
# ./lib/groovehq/client.rb
# ...
def perform_request(path)
url = "https://api.groovehq.com/v1/#{path}"
response = HTTParty.get(url, headers: { 'Authorization' => "Bearer #{@access_token}" })
JSON.parse(response.body)
end
# ...
Let's check if everything works fine by executing bundle exec irb
in the gem directory. Then, one by one, let's execute the following lines of code:
require "./lib/groovehq.rb"
client = GrooveHQ::Client.new("your_access_token")
client.perform_request("me") # me is usually responsible for sending information about the owner of the token back
As a result, if the correct token is used, you will see a hash like this in your console:
{"agent" =>
{
"email" => "fodojyko@gmail.com",
"first_name" => "Kirill",
"last_name" => "Shirinkin",
"href" => "https://api.groovehq.com/v1/agents/fodojyko@gmail.com",
"links" => {
"tickets" => {
"href" => "https://api.groovehq.com/v1/tickets?assignee=fodojyko%40gmail.com"
}
}
}
}
It seems that we have a minimally working gem version! A commit with changes is here: f7d9eef.
The
#perform_request
method is created just for debugging, that's why it doesn't contain a more proper way to create reference strings.
Adding the structure
Having studied the documentation on httparty, I have noticed that this gem allows us to create beautiful and simple classes responsible for delivering requests. You can set global settings for each request (base uri, headers etc.), and each class method will be responsible for a specific request.
Rewritten GrooveHQ::Client
, thus, looks like this (the #perform_request
method is no longer needed):
module GrooveHQ
class Client
include HTTParty
base_uri "https://api.groovehq.com/v1"
format :json
def initialize(access_token = nil)
access_token ||= ENV["GROOVEHQ_ACCESS_TOKEN"]
self.class.default_options.merge!(headers: { 'Authorization' => "Bearer #{access_token}" })
end
end
end
Now let's add separate methods for each API point. In order not to create dozens of methods inside the GrooveHQ::Client
itself, I will split them up into separate modules, where every module is responsible for a definite resource.
It is implemented exactly the same way in octokit gem, where I have overlooked such an approach.
Let's add lib/groovehq/client
directory with tickets.rb
file:
# ./lib/groovehq/client/tickets.rb
module GrooveHQ
class Client
module Tickets
def tickets(options = {})
response = self.class.get("/tickets", { query: options })
response.parsed_response["tickets"]
end
end
end
end
And connect it:
# ./lib/groovehq/client.rb
require "groovehq/client/tickets"
module GrooveHQ
class Client
include HTTParty
include GrooveHQ::Client::Tickets
# ...
The irb
experiment has proved that everything works fine and our first API endpoint is wrapped in a gem and ready to be used.
client = GrooveHQ::Client.new("ACCESS_TOKEN")
client.tickets => returns an array of tickets
Commit: 61f5e78
What's next?
The next task will be to add as many resources as possible, following the API documentation. I will describe the problems I have faced with in this process in my next article.
Series "Development of GrooveHQ Ruby Gem"
- How to create a gem for working with an API
- Writing an API gem: choosing the structure and the tools
- Writing an API gem: how to write tests for an external API
- Writing an API gem: What is Hypermedia API and how to make friends with it
- Writing an API gem: the final metaprogramming