Yanonoblog!

こつこつと

Rails - JSONの解説とjbuilderでのAPI構築

はじめに

本記事では「パーフェクト Ruby on Rails」で学んだ内容と別途気になって調べた内容や知識も含めアウトプットしています。

書籍に記載されている内容を順序立ててまとめるというよりは、整理しておきたい周辺の知識と深ぼった内容を雑多に書いています。

Rails APIJSONを返す

Railsではrenderメソッドなどを使用してビューのHTMLテンプレートを生成して返すこともできますが、APIサーバとして機能させ、JSON形式でのレスポンスを返すことも可能です。

Railsでは、簡単にJSONレスポンスを生成できる仕組みが用意されています。

JSONの構築

renderメソッド呼び出し時にJSONへオブジェクトを変換することができますが、より複雑なJSONデータを構築する場合は、HTMLテンプレートのようにJSONデータを構築する方法ができ、APIとして使用する場合はこの方法が一般的です。

jbuilder

Railsでは、Active Model SerializersやJbuilderといったGemを使用して、JSONデータを構築することができます。

これらのGemを使用すると、宣言的に複雑なJSONレスポンスを作成することができます。

拡張子

Jbuilderで整形されたJSONデータを構築するためのファイルの拡張子は、.json.jbuilderです。この拡張子は、RailsによってJbuilderテンプレートとして認識されます。

コード例

app/controllers/api/v1/users_controller.rb

リクエストによってApi::V1::Settings::UsersControllerindexアクション内の処理が実行され、@usersに適切なデータが設定されたあとビューレンダリングのフェーズに入ります。

# app/controllers/api/v1/users_controller.rb

class Api::V1::UsersController < Api::Base::ApplicationController
  skip_before_action :authenticate!

  def index
    @users = User.all
  end
end
app/views/api/v1/users/index.json.jbuilder

Railsは自動的にビューファイルを探し、適切なJbuilderテンプレートを特定します。

デフォルトの検索パスは、app/viewsディレクトリ内のコントローラーに対応するサブディレクトリです。

この場合、app/views/api/v1/users/index.json.jbuilderJbuilderテンプレートとしての候補となります。

# app/views/api/v1/users/index.json.jbuilder

if @user.blank?
  json.status :error
  json.message I18n.t("errors.no_data")
else
  json.status :success
  json.set! :data do
    json.(@user.decorate, :name, :email)
    if @user.plan.present?
      json.plan do
        json.id @user.plan.id
        json.name @user.plan.name
        end
      end
    end
  end
end

特定されたJbuilderテンプレートが読み込まれ、コントローラー内で定義されたインスタンス変数やローカル変数を使用して、JSONデータの構築が行われます。

Jbuilderテンプレート内で定義されたJSONデータの構築処理が完了し、レスポンスとして返されます。

上記の流れにより、indexアクションに対応するJbuilderテンプレートが特定され、コントローラー内で設定された変数を使用してJSONデータが構築され、最終的にJSONデータがレスポンスとしてクライアントに返されます。

部分テンプレート

jsonもerbと同様に部分テンプレートも使用することができます。

app/views/api/v1/users/_user.json.jbuilder

ユーザー情報を含む部分テンプレート _user.json.jbuilder を作成します。

json.(@user.decorate, :name, :email)

上記のテンプレートでは、@userオブジェクトのnameemail属性をJSONに追加しています。

app/views/api/v1/users/index.json.jbuilder

元のテンプレートである app/views/api/v1/plans/index.json.jbuilder を以下のように修正します。

json.partial! メソッドを使用して、部分テンプレート _user.json.jbuilder を読み込んでいます。引数として user: @user を渡しています。

if @user.blank?
  json.status :error
  json.message I18n.t("errors.no_data")
else
  json.status :success
  json.set! :data do
    json.partial! 'api/v1/plans/user', user: @user
    if @user.plan.present?
      json.plan do
        json.id @user.plan.id
        json.name @user.plan.name
      end
    end
  end
end
解説

json.partial! の第1引数は、部分テンプレートのパスを指定します。

'api/v1/plans/user' と指定することで、_user.json.jbuilder を参照します。

json.partial! の第2引数は、部分テンプレート内で使われる変数を指定します。ここでは user: @user を渡しているので、部分テンプレート内では user としてアクセスできます。

index.json.jbuilder では部分テンプレート _user.json.jbuilder を使用して、ユーザー情報を含むJSONデータが構築されます。

部分テンプレートを利用することで、同じユーザー情報のJSONデータを複数のテンプレートで再利用することができ、部分テンプレートを使うことでコードの可読性や保守性も向上します。

参考

続く…

コメント

本記事の内容は以上になります!

書籍の続きのアウトプットも随時更新したいと思います。


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky