RailsでAPIの実装を依頼され、その時にGrapeを使用しましたので、使用方法を忘れないように書き残しておきたいと思います。
Grapeを使用すると、Restful な WEB-APIが簡単に実装できます。
Grapeの導入
前提
- OS:Centos7
- Rubyのバージョン:2.4.1
- Railsのバージョン:5.1.6
- Railsプロジェクトは作成済
Gemfile
gem 'grape'
上記を追記して、bundle installする。
フォルダ構成
APIのソースはapp/apis/配下に配置することにしました。
ディレクトリ構成およびファイル名は、クラスの名前空間およびクラス名と一致させる必要がありです。(大文字、小文字の区別なし)
この例では、1つのバージョンしか作成しないため、「v1」フォルダのみとなりますが、複数バージョン作成したい場合は、「v2」などのフォルダを作成して下さい。
手順
Config/application.rbを修正
module TestApp
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
最後の2行を追記します。これにより、app/apis/ 配下のRubyファイルが読み込まれるようにします。
基底となるAPIクラスをapp/apis/apiに作成
module API
class Root < Grape::API
# http://localhost:3000/api/
prefix 'api'
mount API::V1::Root
end
end
ここでは、各バージョンの基底となるAPIクラスをマウントしています。
今回は、1つのバージョンのみとなります。
v1の中で基底となるAPIクラスを作成
module API
module V1
class Root < Grape::API
# http://localhost:3000/api/v1/
version 'v1'
format :json
mount API::V1::Articles
end
end
end
ここで各APIの実態をマウントします。
各APIの実態を作成
module API
module V1
class Articles < Grape::API
resource :articles do
# GET /api/v1/articles
desc 'Retrun all article'
get '/' do
Article.all
end
# GET /api/v1/articles/{:id}
desc 'Retrun a article'
params do
requires :id, type: Integer
end
get ':id' do
Article.find(params[:id])
end
end
end
end
end
ここでは、2つのAPIを定義しています。
1つ目は、Articlesテーブルの全データを取得。
2つ目は、Articlesテーブルの中から、パラメータで指定されたIDに合致するデータを取得。
ここで注意すべき点は、クラス名です。
既に存在するクラスと同一の名前は避けるべきです。
今回の例の場合は、APIクラスの名称は「Articles」にしています。
仮に「Article」という名称にすると、Articleモデルのクラス名と同じ名称となるため、Article.allなどのArticleモデルクラスのメソッド実行時にエラーが発生します。
どうしても同一名称にしたい場合は、モデルクラスのメソッド実行時は以下のようにします。
::Article.all
※「::」を前につける
動作確認
rails sにて起動後に、APIのURLをブラウザに入力するとAPIを実行できます。
コマンドを実行して確認することも可能です。
$ curl -X GET http://localhost:3000/api/v1/articles
[{"id":1,"title":"タイトル1","content":"内容1","status":2,"created_at":"2018-06-11T21:47:58.801Z","updated_at":"2018-07-16T21:48:52.106Z","published_at":"2018-07-16T21:48:50.698Z"},{"id":2,"title":"タイトル2","content":"内容2","status":2,"created_at":"2018-06-11T21:47:58.993Z","updated_at":"2018-07-16T21:48:52.805Z","published_at":"2018-07-16T21:48:52.751Z"},{"id":3,"title":"タイトル3","content":"内容3","status":1,"created_at":"2018-06-11T21:47:59.194Z","updated_at":"2018-07-16T21:48:53.025Z","published_at":"2018-07-16T
※一部のみ
$ curl -X GET http://localhost:3000/api/v1/articles/2
{"id":2,"title":"タイトル2","content":"内容2","status":2,"created_at":"2018-06-11T21:47:58.993Z","updated_at":"2018-07-16T21:48:52.805Z","published_at":"2018-07-16T21:48:52.751Z"}