LoginSignup
1
1

More than 3 years have passed since last update.

Jbuilderのレンダリング時間をjsonapi-serializerで改善するTips

Posted at

RailsのViewでJbuilderを使用していて、collectionのレンダリングが遅いなと感じたことはないでしょうか?
その場合、jsonapi-serializer で手軽に改善できるかもしれません。
jsonapi-serializer の詳しい使い方は 公式ドキュメント を見ていただくとして、本記事では Jbuilder を jsonapi-serializer で置換する際のTipsを書きます。
なお完全に置換するのではなく手軽に検証するために Jbuilder と jsonapi-serializer を共存させるハイブリッド形式にしています。(効果が確認でき必要であれば全置換すればいいと思います)

おことわり

とある事情により本記事を書いており、主に時間の制約により以下の注意点があります。

  • 実際のプロジェクトで以前に対応した内容を基に本記事を書いています。結構速くなった記憶はあるのですが、何倍速くなったとか、実際のベンチマークを提示することはできません。
  • 本記事中のコードは動作確認していません。雰囲気だけ参考にしてください。

jsonapi-serializer とは

データをJSON APIフォーマットで出力してくれるgemで、速さをウリにしています。
もとは Netflix/fast_jsonapi で開発されていましたが、メンテナンスされなくなったため有志コミュニティにより fork されました。それからアレコレあり現在の jsonapi-serializer/jsonapi-serializer になりました。

Tips

Serializer Moduleを作成する

先述の通り jsonapi-serializer の出力は JSON API の仕様で定められたフォーマットとなり、jbuilder を置換するには使いにくいです。
そのため以下のような Serializer Moduleを作成します。

module ApplicationSerializer
  extend ActiveSupport::Concern

  included do
    include JSONAPI::Serializer
  end

  class_methods do
    # 短く書きたい場合は以下のようなクラスメソッドがあるといいかもしれません
    # def attributes(...)
    #   new(...).attributes
    # end
  end

  # 必要な部分のみを抽出
  def attributes
    data = serializable_hash[:data]
    case data
    when Hash
      data[:attributes]
    when Enumerable
      data.pluck(:attributes)
    else
      data
    end
  end
end

Jbuilder の show.json.jbuilder など単一リソースに対応する Serializer を作成する

たとえば以下のような感じです。

app/views/posts/show.json.jbuilder
json.extract! @post, :id, :title, :content, :published_at
app/serializers/post_serializer.rb
class PostSerializer
  include ApplicationSerializer

  attributes :id, :title, :content, :published_at
end

show.json.jbuilder の中身を Serializer を使用するように変更する

app/views/posts/show.json.jbuilder
json.merge! PostSerializer.new(@post).attributes

同様に index.json.jbuilder など複数リソースのviewを Serializer を使用するように変更する

app/views/posts/index.json.jbuilder
json.array! @posts, partial: 'posts/post', as: :post

app/views/posts/index.json.jbuilder
json.merge! PostSerializer.new(@posts).attributes

(Serializerに渡すものは単一・複数リソースのどちらでもOKです)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1