Quick Start Guide

This guide will walk you through creating a simple but functional API using Grape. We'll build a small part of a Twitter-like API as an example.

Basic API Structure

Grape APIs are Rack applications that are created by subclassing Grape::API. Here’s a basic example that demonstrates common features like versioning, formatting, helpers, and resource definition.

Create a file named twitter_api.rb:

# twitter_api.rb
require 'grape'

# Assume User and Status models exist
# class User; end
# class Status; end

module Twitter
  class API < Grape::API
    version 'v1', using: :header, vendor: 'twitter'
    format :json
    prefix :api

    helpers do
      def current_user
        # A real implementation would authenticate the user
        @current_user ||= User.new # User.authorize!(env)
      end

      def authenticate!
        # A real implementation would check for a valid session
        # error!('401 Unauthorized', 401) unless current_user
      end
    end

    resource :statuses do
      desc 'Return a public timeline.'
      get :public_timeline do
        # Status.limit(20) - Dummy data for now
        [{ user: 'user1', text: 'hello' }, { user: 'user2', text: 'world' }]
      end

      desc 'Return a personal timeline.'
      get :home_timeline do
        authenticate!
        # current_user.statuses.limit(20)
        [{ user: 'current_user', text: 'my post' }]
      end

      desc 'Return a status.'
      params do
        requires :id, type: Integer, desc: 'Status ID.'
      end
      route_param :id do
        get do
          # Status.find(params[:id])
          { id: params[:id], text: "Status ##{params[:id]}" }
        end
      end

      desc 'Create a status.'
      params do
        requires :status, type: String, desc: 'Your status.'
      end
      post do
        authenticate!
        # Status.create!({ user: current_user, text: params[:status] })
        { user: 'current_user', text: params[:status] }
      end

      desc 'Update a status.'
      params do
        requires :id, type: String, desc: 'Status ID.'
        requires :status, type: String, desc: 'Your status.'
      end
      put ':id' do
        authenticate!
        # current_user.statuses.find(params[:id]).update({ user: current_user, text: params[:status] })
        { id: params[:id], text: params[:status] }
      end

      desc 'Delete a status.'
      params do
        requires :id, type: String, desc: 'Status ID.'
      end
      delete ':id' do
        authenticate!
        # current_user.statuses.find(params[:id]).destroy
        { id: params[:id], status: 'deleted' }
      end
    end
  end
end

Running the API

Since Grape is a Rack application, you can run it with any Rack-compatible server like Puma or Thin. The simplest way is using rackup.

Create a config.ru file in the same directory:

# config.ru
require './twitter_api'

run Twitter::API

Now, start the server from your terminal:

$ rackup

Interacting with the API

Your API is now running! It will respond to the following routes:

  • GET /api/statuses/public_timeline
  • GET /api/statuses/home_timeline
  • GET /api/statuses/:id
  • POST /api/statuses
  • PUT /api/statuses/:id
  • DELETE /api/statuses/:id

Here's how you can interact with it using curl. Note the Accept header, which is required because we specified using: :header for versioning.

Get the public timeline:

$ curl -H "Accept: application/vnd.twitter-v1+json" http://localhost:9292/api/statuses/public_timeline
[{"user":"user1","text":"hello"},{"user":"user2","text":"world"}]

Create a new status:

$ curl -X POST -H "Accept: application/vnd.twitter-v1+json" -H "Content-Type: application/json" -d '{"status":"Grape is awesome!"}' http://localhost:9292/api/statuses
{"user":"current_user","text":"Grape is awesome!"}

Congratulations, you've just built and run your first Grape API! To learn more about its features, dive into the Core Concepts.