Nowadays the importance of Restful APIs has increased a lot for web and mobile apps. Writing API has been made easier and pretty good by some API Builders in Ruby. There are plenty frameworks and gems available for this. Some are
- ActiveModel::Serializers – JSON serialization of objects.
- Crêpe – The thin API stack.
- Grape – An opinionated micro-framework for creating REST-like APIs in Ruby.
- jbuilder – Create JSON structures via a Builder-style DSL.
- JSONAPI::Resources – JSONAPI::Resources, or “JR”, provides a framework for developing a server that complies with the JSON API specification.
- Jsonite – A tiny, HAL-compliant JSON presenter for your APIs.
- Pliny – Opinionated template Sinatra app for writing excellent APIs in Ruby.
- rabl – General ruby templating with json, bson, xml, plist and msgpack support.
- Rails::API – Rails for API only applications.
- Roar – Resource-Oriented Architectures in Ruby.
After building your awesome API the most important thing to do is writing specs for your API. A few weeks ago, I heard about the ‘airborne’ gem. I tried it out and it was really good. I would like to share the experience with you.
Airborne is an RSpec driven testing framework just for APIs. According to the docs this framework was inspired by frisby.js which is also a REST API testing framework but built on Node.js and Jasmine.
To try this out, lets create a sample Rails app to manage events. So go ahead and create a new Rails application and generate the ‘Event’ model.
[source language=”bash”]
$ rails new airborne-sample-app
$ rails g model Event title:string event_date:date location:string description:text
[/source]
Now lets use Grape to create an API to access Events. If you not familiar with Grape, just use default API Builder ‘jBuilder’ that comes with Rails 4 apps.
Using Grape let’s create a simple RESTful API as shown
[source language=”ruby”]
module API
module V1
class Events < Grape::API
#### PATH Versioning
version 'v1'
format :json
before do
error!('401 Unauthorized', 401) unless headers['Password'] == 'spritle'
end
### Using namspace or resource to define routes
namespace :events do
desc "Return list of events"
get :list do
events = Event.all
present :success, true
present :events, events
end
get ':id', requirements: { id: /[0-9]*/ } do
event = Event.find(params[:id])
present :success, true
present :event, event
end
post 'create' do
event = Event.create(params[:event])
present :success, true
present :event, event
present :message, "Successfully created"
end
delete ':id' do
event = Event.find(params[:id])
event.delete
present :success, true
present :message, "Successfully deleted"
end
end
end
end
end
[/source]
Thus we have an API to do basic CRUD on Events.
Let's see how we can test this API using 'airborne'.
Include the following gems in the Gemfile.
[source language="ruby"]
gem 'rspec-rails', group: [:development, :test]
gem 'airborne', '> 0.1.1′
[/source]
Create /spec directory using rspec command
[source language=”ruby”]
$ rails generate rspec:install
[/source]
It adds the following files under /spec directory
[source language=”ruby”]
spec/spec_helper.rb
spec/rails_helper.rb
[/source]
Now create /api folder under the spec folder for the API specs. Then create ‘events_spec.rb’ file in it where we will write the specs for the Events API.
Below is the spec I wrote for the API:
[source language=”ruby”]
require ‘rails_helper’
describe “Events API” do
fixtures :events
it “Events List API should throw exception when password is not passed” do
get “/api/v1/events/list.json” # test for the 200 status-code
expect_status(“401”)
expect_header(“Content-Type”,”application/json”)
expect_json({:success =>false,:message => “401 Unauthorized”})
end
it “Events List API should return events list with proper data types” do
get “/api/v1/events/list”, {}, {“Password” => “spritle”}
expect(response).to be_success
expect_json_types(‘events.*’, {id: :integer,title: :string})
expect_json(“events.0”,{:id => 1,:title => “SpriteXchange Nov Event”})
expect_json_keys(‘events.0’, [:id, :title])
end
end
[/source]
Before run the spec, we should create some sample data for testing using fixtures and add fixtures for events in the “event_spec.rb”
In the /spec/fixtures/events.yml
[source language=”ruby”]
one:
id: 1
title: SpriteXchange Nov Event
[/source]
Now lets run the specs
[source language=”bash”]
$ rspec spec
[/source]
We are simply testing the status, header, JSON types and JSON format 🙂 in the Rails application.
Using ‘airbone’ we can test any Rack application. If you need to test your Rack application you can configure it like this:
[source language=”ruby”]
Airborne.configure do |config|
config.rack_app = MySinatraApp
end
[/source]
I hope this would be helpful for you :-). The source code of the app created here is available at Airbone-Sample.