Grape を利用すると Restful な WEB-API が簡単に作成できるらしいので試してみました。その際、実際の運用を視野にいれて、次のこともやってみました。
-
複数の API バージョン に対応する。
- 例:
http://ドメイン/api/v1/..
http://ドメイン/api/v2/..
- 例:
- 1つのソースがファットにならないよう モデル毎にソースを分ける 。
まずは Grape の導入手順から説明します。
Grape の導入手順
前提
- 手元の OS:
Mac OS X 10.9.5 (Mavericks)
- Ruby:
2.1.2
- Rails:
4.1.1
Grape は結果、0.9.0
が入りました。
手順
-
適当な Rails プロジェクトを作成。
$ bundle exec rails new grape_app --skip-bundle -T
-
Gemfile への追記。
Gemfile#.. gem 'grape' #..
-
gem をインストール。
$ cd grape_app $ bundle install --path vendor/bundle
API の作成
前提
APIのソースコードは app/apis/
下に置くこととします。ファイル構成はこんな感じ。
ディレクトリ構成およびファイル名は、クラスの名前空間およびクラス名と一致させる必要があります。 大文字/小文字は、気にしなくてもいいみたい。
手順
-
適当に Scaffold します。
$ ./bin/rails g scaffold person name:string age:integer memo:text $ ./bin/rails g scaffold product name:string price:integer memo:text $ ./bin/rake db:migrate
※
Person
モデルとProduct
モデルが作られます。 -
app/apis/
下の Ruby ファイルが読み込まれるようにします。config/application.rb#.. module GrapeApp class Application < Rails::Application #.. config.paths.add File.join('app', 'apis'), glob: File.join('**', '*.rb') config.autoload_paths += Dir[Rails.root.join('app', 'apis', '*')] end end
-
基底となるAPIクラスを作成します。
- このファイルで各バージョンのAPIをマウントします(今回は、バージョン1のみ)。
app/apis/api/root.rbmodule API class Root < Grape::API # http://localhost:3000/api/ prefix 'api' mount API::Ver1::Root #mount API::Ver2::Root end end
-
バージョン1の中で、基底となるAPIクラスを作成します。
- ここで 各APIの実体をマウントします。
app/apis/api/ver1/root.rbmodule API module Ver1 class Root < Grape::API # http://localhost:3000/api/v1/ version 'v1' format :json mount API::Ver1::People mount API::Ver1::Products end end end
-
各APIの実体を作成します。
- 今回は「全件取得」と「1件取得」のAPIを作成します。
app/apis/api/ver1/people.rbmodule API module Ver1 class People < Grape::API resource :people do # GET /api/v1/people desc 'Return all people.' get do Person.all end # GET /api/v1/people/{:id} desc 'Return a person.' params do requires :id, type: Integer, desc: 'Person id.' end get ':id' do Person.find(params[:id]) end end end end end
app/apis/api/ver1/products.rbmodule API module Ver1 class Products < Grape::API resource :products do # GET /api/v1/products desc 'Return all products.' get do Product.all end # GET /api/v1/products/{:id} desc 'Return a product.' params do requires :id, type: Integer, desc: 'Product id.' end get ':id' do Product.find(params[:id]) end end end end end
-
最後に、基底となるAPIクラスをルーティングに追加します。
config/routes.rbRails.application.routes.draw do #.. mount API::Root => '/' #.. end
動作確認
適当にデータを登録し、ブラウザでアクセスしてみます。
おわりに
簡単に API が作成できました。自身の課題として、次のものがあります。
- Grape の GitHubページ に記載されている機能を検証できていない
- エラーのハンドリングまわりの実装
- JSONデータの入れ子に対応できるよう、テンプレートエンジンを導入(rabl が良い?)
今回はわりとよい感触を得られたので、引き続き触って評価してみようと思います。