酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Grape - RailsでスピーディにAPIを作成!

RailsやSinatra、RubyでAPIを作成する際に便利なGem『Grape』の紹介です。

このGemは簡単にjson、xml、txtなどのAPIを作成できます。それだけではなく、APIのバージョン管理やパラメータのバリデーション、モジュール化など、本格的なAPIを作る上で必要になる機能も持っています。

今回はハッカソンの中で初めてGrapeを使ってJSON APIを作ったので内容は浅めですが、備忘録として残しておきます!もしなにかお気づきの点等有ればコメントください。


Gemのインストール

Gemfileに以下を追加して、コンソールでbundleを実行してください。

1
2
# API Support
gem 'grape'

APIのサンプル

Twitterを模倣したサンプル(?)が、公式のGitHubのREADMEに書かれていたので転載。

app/api/twitter.rbを作成して、以下のようなコードを書きます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
module Twitter
  class API < Grape::API
    # versionは:headerや、:paramなどもあり
    version 'v1', using: :path, vendor: 'twitter'
    format :json

    helpers do
      def current_user
        @current_user ||= User.authorize!(env)
      end

      def authenticate!
        error!('401 Unauthorized', 401) unless current_user
      end
    end

    resource :statuses do
      desc "Return a public timeline."
      get :public_timeline do
        Status.limit(20)
      end

      desc "Return a personal timeline."
      get :home_timeline do
        authenticate!
        current_user.statuses.limit(20)
      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])
        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]
        })
      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]
        })
      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
      end
    end
  end
end

パラメータの必須・任意の制御

APIでパラメータを必須にする場合と、任意にする場合はこちらのDSLで制御。

1
2
3
4
requires :id, type: String # => 必須
optional :text, type: String #=> 任意
optional :status, type: String regexp: /^[a-z]+$/ #=> regexpで正規表現チェック
optional :color, type: String, default: 'blue' #=> defaultで初期値

バリデーションはAPIの要なので、かなり考えられている印象です。詳しくは、公式GitHubの説明がわかりやすいです。

Rails側への設定

Railsでapiファイルを自動で読み込むように、config/application.rbに以下のコードを追加。

1
2
config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]

APIのルーティングを追加。

1
mount Twitter::API => '/'

まとめ

ということでAPIを簡単・スピーディに構築できました。 また別のプロジェクトでAPIを作成したら、内容を追加していきます!

Special Thanks

intridea/grape Wiki

Ruby - RailsとGrapeで行う最高のWeb API開発

Grape + RSpec + json_expressions で Awesome な API の受け入れテスト

Rails - Grape | API生成マイクロフレームワーク

おすすめの書籍