Grape + Grape Entity で作る API
Grape をよく使うので基本的な使い方から開発方法などを記す。 あと思いの外 Grape Entity が便利なので小技などをまとめておきたい。
Grape とは
Rails で RESTful な API を開発するためのフレームワーク。 Rails5 から提供された API モードで普通の Controller で簡単に開発することは可能になったが、 Grape の場合 REST に特化した DSL のためコードが追いやすい。
また Grape Entity と組み合わせることによってエンドポイント特有の結果を提供することが用意になる。
個人的にはコードが簡潔に保てるところが一番の強みだと思っている。
導入方法
「Grape 導入」で調べるといっぱい出てくるので割愛したい。 個人的に気にっているフォルダ構成は以下だ。
├── api │ ├── base │ │ └── api.rb │ └── v1 │ ├── entities │ │ ├── group_entity.rb │ │ ├── idol_entity.rb │ │ └── song_entity.rb │ ├── groups.rb │ ├── idols.rb │ ├── root.rb │ └── songs.rb
まず Rails プロジェクトの app 配下に api ディレクトリを作る。 そこに base と v1 というディレクトリを作る。 v1 ディレクトリはいわゆる API のバージョニングのためのもの。
api/base/api.rb と routes.rb にはそれぞれ以下が記述されているものとする。
# api/base/api.rb module Base class API < Grape::API mount V1::Root end end # routes.rb mount Base::API => '/'
こうすることによって API へのリクエストはすべて base/api.rb に流れる。 base の方の記述を見ると v1 に受け流している。 こうすることによって API のバージョンニングを用意にしている(のだと思う)。
v1 配下は Grape を記述していくところで entity ディレクトリは Grape Entity を記述するところである。
それでは Grape の構文を見ていく。
シンタックス
Grape
module V1 class Idols < Grape::API resources :idols do desc 'return all idol' get '/' do @idols = Idol.all present @idols, with: V1::Entities::IdolEntity end end desc 'Create an idol' params do requires :name, type: String requires :group_id, type: Integer end post do @idol = Idol.new(name: params[:name], group_id: params[:group_id]) if @idol.save status 201 present @idol, with: V1::Entities::IdolEntity else status 400 present @idol.errors end route_param :id do desc 'returns an idol' get do @idol = Idol.find(params[:id]) present @idol, with: V1::Entities::IdolEntity end end end end end
見ただけでどこに何が書いてあるかがわかりやすいと思います。 基本構文は以下のような感じです。
resource :{操作を加えるリソース名(モデル名)do desc '説明' paras do # パラメータを記述 end {HTTP のメソッド} do # 処理 end end
このように記述することによって以下の操作が可能。
- GET: /idols ... 一覧の取得 - GET: /idols/1 ... 1件取得 - POST: /idols ... 作成
リソースの中にリソースをネストさせることも可能。
resource :groups do ... resource :idols do ... end end
この場合 idols
には /groups/idols
という URI でアクセスすることができる。
Grape Entity
上の例にも出てきているが present @idol, with: V1::Entities::IdolEntity
の IdolEntity がそれである。
このファイルは以下のように記されている。
module V1 module Entities class IdolEntity < Grape::Entity expose :id expose :name expose :group, using: V1::Entities::GroupEntity end end end
expose に指定したフィールドをオブジェクトに問い合わせてその値を返してくれる。 この場合以下のような JSON オブジェクトが返ってくる。
{ id: 1, name: "test", group: { id: 1, name: "test" } }
ここでネストをさせているが Idol モデル belongs_to で Group に紐づくとする。 その場合紐づく group をたどって指定した GroupEntity に当てはめてくれる。
またモデルクラスに定義されているメソッドを返すこともできる。 例えば以下のような例が挙げられる。
module V1 module Entities class IdolEntity < Grape::Entity expose :id expose :name do |idol| idol.full_name end expose :group, using: V1::Entities::GroupEntity end end end
Idol クラスに full_name というメソッドが定義されているとする。
上のように expose :name
にブロックを渡してあげることにより full_name の値を name として返すことができる。
まとめ
Grape を使って開発すると Controller に書くのに比べて可読性の高いコードが書けることがわかった。