Grape で Web API 開発 - kzy52's blog
前回は Jbuilder を使いましたが 今回はGrape::Entityというgemを使ってJSONフォーマットを実装していきたいと思います。
ディレクトリ構成とルーティングは以下のようになる予定です。
├── app │ ├── apis │ │ ├── api │ │ │ ├── base.rb │ │ │ ├── v1 │ │ │ │ ├── base.rb │ │ │ │ ├── comments.rb │ │ │ │ └── message_boards.rb │ │ │ └── v2 │ │ │ ├── base.rb │ │ │ ├── comments.rb │ │ │ └── message_boards.rb │ │ └── entity │ │ ├── v1 │ │ │ ├── comments_entity.rb │ │ │ └── message_boards_entity.rb │ │ └── v2 │ │ ├── comments_entity.rb │ │ └── message_boards_entity.rb
Gem のインストール
# Gemfile gem 'grape' gem 'grape-entity'
$ bundle install
Entity の実装
# app/apis/entity/v1/message_boards_entity.rb module Entity module V1 class MessageBoardsEntity < Grape::Entity # {"message_boards":[]} # {"message_board":{} } # というJSON出力になります。 root 'message_boards', 'message_board' expose :id, :title, :body # 値を加工することができる。 expose :updated_at do |message_baord, options| message_baord.updated_at.strftime("%Y-%m-%d %H:%M:%S") end # 他のEntityの定義を使うことができる。 expose :comments, using: 'Entity::V1::CommentsEntity' expose(:comment_count) do |message_board| message_board.comments.count(:id) end end end end
# app/apis/entity/v1/comments_entity.rb module Entity module V1 class CommentsEntity < Grape::Entity # {"comments":[]} # というJSON出力になります。 root 'comments' expose :id, :body, :updated_at end end end
Entity を APIで指定する
# app/apis/api/v1/message_boards.rb module API module V1 class MessageBoards < Grape::API resource :message_boards do desc 'GET /api/v1/message_boards' get '/' do @message_boards = MessageBoard.all # 定義したエンティティはAPI側で指定する。 present @message_boards, with: Entity::V1::MessageBoardsEntity end ... desc 'GET /api/v1/message_boards/:id' params do use :id end get '/:id' do set_message_board present @message_board, with: Entity::V1::MessageBoardsEntity end ... end end end
module API module V1 class Comments < Grape::API resource :message_boards do params do use :message_board_id end route_param :message_board_id do resource :comments do desc 'GET /api/v1/message_boards/:message_board_id/comments' get '/' do set_message_board @comments = @message_board.comments present @comments, with: Entity::V1::CommentsEntity end ... end end end
Jbuilderより書きやすくていいですね。
ただEntityクラスをどこに配置するか悩ましいですね。
今回はディレクトリを切ってバージョニングしているのでこの方法にしてみました。