GET /ping
で {"response": "pong"}
を返すAPIサーバを、Ruby製REST-like APIフレームワーク「grape」で作成する最小構成。
ファイル/ディレクトリ構成
.
├── Gemfile
├── Procfile
├── config.ru
├── api.rb
└── spec
├── spec_helper.rb
└── api_spec.rb
ユニットテスト
bundle exec rspec spec/api_spec.rb
ローカル開発
bundle exec rackup
## もしくは
heroku local:start
ファイル解説
Gemfile
bundle init
で作成した後、以下を行う。
- Ruby のバージョン指定 (Heroku向け)
- grape、rspec、puma の指定
- rack-test はユニットテスト(RSpec)向け
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
ruby "~> 3.0.0"
gem "grape"
gem "rspec"
gem "puma"
group :development do
gem "rack-test"
end
Procfile
Procfile は Heroku 向け。Herokuを使わない場合は不要。
web: bundle exec rackup config.ru -p $PORT
config.ru
rackup 向け。
require_relative File.join("api")
run APIserver
api.rb
API本体。
require "grape"
class APIserver < Grape::API
format :json
get "/ping" do
{"response": "pong"}
end
end
spec/spec_helper.rb
RSpec向け。
require_relative
は config.ru と同じものを指定していく。
require "rack/test"
以下は grape/RSpec に書いてある通り、おまじない的。 app
が API のインスタンスを返すようにする必要がある。
require_relative File.join("..", "api")
require "rack/test"
include Rack::Test::Methods
def app
APIserver
end
spec/api_spec.rb
ユニットテスト本体。
require "spec_helper"
context "GET ping" do
it "return pong" do
get "/ping"
expect(last_response.status).to eq(200)
expect(JSON.parse(last_response.body)).to eq({"response" => "pong"})
end
end
今後の拡張ポイント
rackup(webサーバ)のエントリーポイントは config.ru
、RSpec(ユニットテスト)のエントリーポイントは spec_helper.rb
です。require等はここに集中する(もしくは共通化)するようにしましょう。
APIのデータ構造を実装したければ、grape-entityが使えます。Nestedな1:N構造も実装可能です。RESTful APIにおいて一対多関係のデータ構造をGrape::Entityを使って表現する
複雑なJSONの検証には rspec-json_matcher が使えます。複雑なケースの例は rspec-json_matcherでJSONの検証を自由自在に行う をご覧ください。
EoT