Build Great APIS with Grape

Share this article

big_grape

APIs are needed for various reasons, such as by mobile apps to interact with backend CRUD operations. Creating maintainable APIs is not a simple task. As the application grows, so does the need to version and maintain the API.

In this tutorial, we’ll have a look at Grape, a micro-framework for creating maintainable REST-like APIs in Ruby.

From grape’s Github page:

Grape is a REST-like API micro-framework for Ruby. It’s designed to run on Rack or complement existing web application frameworks such as Rails and Sinatra by providing a simple DSL to easily develop RESTful APIs. It has built-in support for common conventions, including multiple formats, subdomain/prefix restriction, content negotiation, versioning and much more.

Our Project

We’ll be using Rails and grape together to create the API. It will expose the Employee model to other applications, consuming the back-end CRUD operations for that model.

The API can be used by rich web applications, like the ones created using AngularJS, Backbone.js, etc. or native mobile applications to create, edit, update, and delete employees.

Here are the API endpoints we’ll be creating:

//Get all employee details
GET /emp_api       

//Add an employee
POST /emp_api/  {name:"Jay", address:"Kerala, India", age:"34"}             

//Delete an employee         
DELETE /emp_api/1

//Update an employee
PUT /emp_api/1

Getting Started

Let’s start by creating a Rails application and installing the Grape gem. I’m using Rails 4.1.6.

Create a new Rails project, skipping the bundle install.

rails new emp_api --skip-bundle

Once the project files are all created, navigate to the project directory (emp_api). Open the Gemfile and include the grape gem at the end of the file.

gem 'grape'

Next, install all the required gems using Bundler:

bundle install

Generate an Employee model for the basic CRUD operations to be exposed by the API:

rails g model EmpData name:string address:string age:integer
rake db:migrate

All the API files will live inside the app folder. Create a new folder called api inside emp_api/app/.

Inside emp_api/app/api create another folder called employee, and a file in that directory called data.rb. This file holds the class to access the Employee model.

Inside emp_api/app/api/ create another file called api.rb where we’ll mount the class defined in emp_api/app/api/employee/data.rb.

As per the instructions on the Grape GitHub pages, since we have placed our API code in app/app, that directory needs to be added to the load/autoload paths. Set it up in config/application.rb as shown below:

require File.expand_path('../boot', __FILE__)

require 'rails/all'

Bundler.require(*Rails.groups)

module EmpApi
  class Application < Rails::Application
    ## Newly Added code to set up the api code
    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
  end
end

Creating the API

Grape APIs are Rack applications that are created by subclassing Grape::API. Let’s get started by creating the first API endpoint to retrieve all employee details. Open up app/api/employee/data.rb and create the module class as shown:

module Employee
  class Data < Grape::API

    resource :employee_data do
      desc "List all Employee"

      get do
        EmpData.all
      end

    end

  end
end

We need to access the Employee::Data class functionality inside the API class. So, we’ll use mount to make Employee::Data class accessible inside the API class.

So, open up app/api/api.rb and mount Employee::Data

class API < Grape::API
  prefix 'api'
  version 'v1', using: :path
  mount Employee::Data
end

Open up app/config/routes.rb and include the following code to route the API calls to our root address:

Rails.application.routes.draw do
  mount API => '/'
end

Fire up the rails server:

rails server

Open a new terminal and try :

curl http://localhost:3000/api/v1/employee_data.json

You’ll see [] as response, since we don’t have any data yet. We don’t have any way to add employees, so let’s fix that.

Add another API endpoint to create a new employee. We’ll need certain values to create an employee, such as name, address, and age. Grape allows us to define whether these parameters are required or optional in the API itself.

Open app/api/employee/data.rb and add the following code to create the API endpoint for employee creation.

desc "create a new employee"
## This takes care of parameter validation
params do
  requires :name, type: String
  requires :address, type:String
  requires :age, type:Integer
end
## This takes care of creating employee
post do
  EmpData.create!({
    name:params[:name],
    address:params[:address],
    age:params[:age]
  })
end

Restart the server and use curl to post a request to the endpoint:

curl http://localhost:3000/api/v1/employee_data.json -d "name=jay;address=delhi;age=25"

Now, we should have an employee:

curl http://localhost:3000/api/v1/employee_data.json

[{"id":1,"name":"jay","address":"delhi","age":25,"created_at":"2014-10-27T16:43:49.303Z","updated_at":"2014-10-27T16:43:49.303Z"}]

Bingo.

The delete and update API for the employee model follow the similar pattern to our read and create endpoints. The delete endpoint requires the employee ID:

# app/api/employee/data.rb

 desc "delete an employee"
 params do
   requires :id, type: String
 end
 delete ':id' do
   EmpData.find(params[:id]).destroy!
 end

Restart the Rails server and test the API by deleting the employee we created earlier.

curl -X DELETE http://localhost:3000/api/v1/employee_data/1.json

{"id":1,"name":"jay","address":"delhi","age":25,"created_at":"2014-10-27T16:43:49.303Z","updated_at":"2014-10-27T16:43:49.303Z"}

Now, if you check the employee listing api, you should get a empty response.

Next, in order to update an employee details, we’ll need to pass the employee ID and the values to be updated. Add the following code to create an API endpoint to update the employee address:

# app/api/employee/data.rb

desc "update an employee address"
params do
  requires :id, type: String
  requires :address, type:String
end
put ':id' do
  EmpData.find(params[:id]).update({
    address:params[:address]
  })
end

But we don’t have an employee to update. Remember, we deleted the last employee, so we’ll need to add one back in order to update it.

Restart the server and add a new employee first,

curl http://localhost:3000/api/v1/employee_data.json -d "name=roy;address=kerala;age=25"

{"id":2,"name":"roy","address":"kerala","age":25,"created_at":"2014-10-27T16:59:54.090Z","updated_at":"2014-10-27T16:59:54.090Z"}

Now, use the following command to update the address of the new employee:

curl -X PUT http://localhost:3000/api/v1/employee_data/2.json -d "address=mumbai"

true

Wrapping It Up

In this tutorial, we got started creating a simple CRUD API using the Grape framework. Detailed documentation regarding Grape is available on their GitHub pages.

Code from this tutorial is available on GitHub.

Frequently Asked Questions (FAQs) about Building APIs with Grape

How do I install Grape in my Ruby application?

To install Grape in your Ruby application, you need to add the Grape gem to your Gemfile. Open your Gemfile and add the following line: gem 'grape'. Then, run bundle install in your terminal to install the gem. After the installation, you can include Grape in your application by adding require 'grape' at the top of your Ruby file.

How can I define routes in Grape?

In Grape, routes are defined within the API class. You can define a route by specifying the HTTP method (get, post, put, delete), the path, and a block that will be executed when the route is hit. For example, to define a GET route at ‘/hello’, you would write: get '/hello' do 'Hello World' end.

How can I handle parameters in Grape?

Grape provides a params method that you can use to access parameters in your routes. You can define required and optional parameters using the requires and optional methods respectively. For example, to require a ‘name’ parameter in a POST route, you would write: requires :name, type: String.

How can I handle errors in Grape?

Grape provides a rescue_from method that you can use to handle exceptions in your API. You can specify the type of exception to rescue from and a block that will be executed when the exception is raised. For example, to rescue from a RecordNotFound exception, you would write: rescue_from ActiveRecord::RecordNotFound do |e| error_response(message: e.message, status: 404) end.

How can I version my API in Grape?

Grape provides several strategies for versioning your API, including path, header, and parameter. You can specify the versioning strategy and the versions of your API using the version method. For example, to version your API using the path strategy, you would write: version 'v1', using: :path.

How can I return JSON responses in Grape?

By default, Grape returns responses in the format specified in the ‘Accept’ header of the request. However, you can force Grape to return responses in JSON format by adding format :json at the top of your API class.

How can I validate parameters in Grape?

Grape provides several methods for validating parameters, including requires, optional, exactly, and at_least. You can specify the type of the parameter, whether it is required or optional, and additional validation options. For example, to require a ‘name’ parameter of type String, you would write: requires :name, type: String.

How can I use middleware in Grape?

Grape allows you to use Rack middleware in your API. You can add middleware to your API using the use method. For example, to use the Rack::Cors middleware, you would write: use Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post, :put, :delete, :options] end end.

How can I test my Grape API?

You can test your Grape API using any Ruby testing framework, such as RSpec or MiniTest. Grape provides a Grape::API::TestCase class that you can use to write tests for your API. For example, to test a GET route at ‘/hello’, you would write: get '/hello' assert last_response.ok? assert_equal 'Hello World', last_response.body.

How can I document my Grape API?

Grape provides a desc method that you can use to document your API. You can specify the description of a route, the parameters it accepts, and the response it returns. For example, to document a GET route at ‘/hello’, you would write: desc 'Returns a greeting' get '/hello' do 'Hello World' end.

Jay is a Software Engineer and Writer. He blogs occasionally at Code Handbook and Tech Illumination.

GlennG
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week