Rails4から事実上標準になったっぽいJbuilderを使って、Grape+RailsなWebAPIのJSONフォーマットを柔軟に作ってみる。has_manyなどで深い階層のモデルを使ってAPIを作ると面倒くさいことが多いんだけど、Jbuilderならシンプルに書くことが出来る。
他のGemでActiveModel::Serializersっていうのもあったけど、こっちはモデルで出力フォーマットを定義していくタイプっぽくて、複雑なJSONフォーマットにしようとすると面倒。Viewで定義できるJbuilderの方が良さげ。ActiveModel::SerializersはモデルとAPIが1対1の時に良いのかも。
前提
- Rails v4.1
- grape v0.9.0
- grape-jbuilder v0.2.0
Gemfile
gem 'jbuilder'
gem 'grape'
gem 'grape-jbuilder'
$ bundle install
Jbuilderを使ってJSONフォーマットを作ってみる
GrapeとJbuilderの準備
自動読み込み対象に/api/ディレクトリを追加。そして、JbuilderのViewパスを設定する。
module Samples
class Application < Rails::Application
config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += %W(#{config.root}/app/api)
config.middleware.use(Rack::Config) do |env|
env['api.tilt.root'] = Rails.root.join 'app', 'views', 'api'
end
end
end
ルーティングも適当に設定。
mount API => "/api"
APIコントローラ
formatterをJbuilder指定して、各アクションにテンプレートファイルを指定してあげればOK。
class API < Grape::API
format :json
formatter :json, Grape::Formatter::Jbuilder
get '/', jbuilder:'article/index' do
@articles = Article.all
end
end
Jbuilderテンプレート
json.ほげ
で、JSONのキーを割り当てられる。キーを割り当てたくない場合はjson.(@articles)
のようにしてあげれば直下に配置される。
json.articles @articles do |article|
json.(article, :id, :title)
end
{
articles: [
{
"id": 1,
"title": "hoge",
},
{
"id": 2,
"title": "piyo",
}
]
}
これで、非常に簡単に複雑なJSON APIを作ることができそう。
Jbuilderの書き方は本家のREADMEを読めばだいたい分かる。