はじめに
みなさん、こんにちは torihaziです
今日はタイトル通り 数あるRailsのSerializerのgemを色々使ってみて
どれが自分にとって使いやすいかを検証していこうと思います。
メンテがされてるされてない、重い重くないとかは気力があったら書いていきます。
とにかく使いやすいか否か。
ここでいう使いやすいか否かの判断基準は 定義とかfrontendでの取り出し方とかです
前提条件
筆者はfrontendから useSWR x axiosを使ってデータを取得しようとしています。
そのためレスポンスの形は
interface AxiosResponse<T = any> { data: T; // 実際のレスポンスデータ status: number; statusText: string; headers: any; config: any; }
こんな感じで帰ってきます。これを前提としてbackendでSerializer使ってきます
エントリーNo.1 jsonapi-serializer(fast_jsonapi)
gemfileに
gem 'jsonapi-serializer'
してbundle installした後にapp/serializers/ファイル名_serializer.rb
作って
# frozen_string_literal: true class TweetIndexWithImagesSerializer include JSONAPI::Serializer set_type :tweet attribute :id, :content, :image_urls end
とする。
でcontrollerで
def index tweets = Tweet.all json_string = TweetIndexWithImagesSerializer.new(tweets).serializable_hash render json: { message: '成功', data: json_string }, status: :ok end
みたいにして呼ぶとレスポンスは
data: { data: { data: { 0: { id: 数字 type: tweet attributes: { content: "hoge" image_urls: [~~~~,~~~・・・] } } ,・・・・ } } }
何個data のkeyがあるんじゃい。
1個目はaxiosのdata、2個目は rails のcontrollerで定義したやつ、3個目はjsonapi-serializerのやつ。
あとserializerでactivestorageのurl返す時詰まったら下記を参照
Serializerで画像のurlをjsonで返す際に発生したエラー #Ruby - Qiita
ok。次。
エントリーNo2 activemodel-serializer
色々触ろうと思いましたが、GithubのReadmeに「いったん開発やめるわ」みたいなこと書いてあったので却下。
ただ代替案をご丁寧に書いてくれていたのでそれをみてみることに。
エントリーNo3 jsonapi-rails
代替案1つ目らしいっす。
Start by adding the following to your Gemfile: gem 'jsonapi-rails' Then, once your serializable resources are defined, building a JSON API document from your business objects is straightforward: simply pass them to the render method.
gem入れて
render jsonapi: Tweet.all てすればいけるらしいけど。
ドキュメント見てわかったけど、ドキュメントがしょぼい気がする。
不親切といった感じ。自分の読解力がないだけかもしれない。
とりあえず使ってみて、使い方は2つ?あるっぽい。使い方が悪いのかもしれないけど
app/serializers/serializable_tweet.rb作って
# app/serializable/serializable_tweet.rb class SerializableTweet < JSONAPI::Serializable::Resource type 'tweets' attributes :content, :image_urls # 必要な属性を指定 # 関連付けがある場合 # has_one :user # has_many :likes end
てした後に コントローラで
render jsonapi: Tweet.all
て感じで呼び出すと
data: { data: { 0: { id: 数字 type: tweets (<= typeで設定した時の文言、してなければunknown) attributes: { content: "hoge" image_urls: [~~~~,~~~・・・] } } ,・・・・ }, jsonapi: ・・・ }
attributesていうのは出るっぽい。ちなみに前みたいに
render json: {jsonapi: Tweet.all, message: "成功"}
てやったとしてもなんかいけた。
そうしたら
data: { jsonapi: { 0: { id: 数字 content: "hoge" created_at: updated_at: } ,・・・・ }, }
モデルTweetが持つ全カラムが出力されたが、image_urlsが消えた。あとtypeの記載も。
attributesも消えたけどなんかバグっぽい。
これもないかな。
エントリーNo4 jsonapi_resources
んーよくわからん。
次。
エントリーNo 5 alba
名前かっこいい。笑
それに最高。
求めてた形で帰ってきた。
設定方法はこれを参照
config/initializer/alba.rbに
# alba.rb Alba.backend = :active_support Alba.inflector = :active_support
てして
app/resources/base_resource.rbに
class BaseResource include Alba::Resource end
app/resources/tweets_with_images_resource.rbに
class TweetsWithImagesResource < BaseResource root_key :tweet <= 対象のモデル attributes :id, :content, :image_urls end
ちなみにimage_urlsはtweet.rbにおいてこう定義してる。
# frozen_string_literal: true class Tweet < ApplicationRecord include Rails.application.routes.url_helpers belongs_to :user has_many_attached :images def image_urls images.map { |image| url_for(image) } if images.attached? end end
コントローラは
tweets = Tweet.all render json: {message: '成功', data: TweetsWithImagesResource.new(tweets)}
としたらレスポンスは
data: { data: { 0: { id: 数字 content: "hoge" image_urls: [~~~~,~~~・・・] } ,・・・・ } } config: ・・・
みたいな感じで理想のができた
attributesとかも出てないし、typeも出てないし。
君に決めた!
終わりに
長きにわたる最適なRails Serializer探しの旅終了。
選ばれたのは albaでした。
異論認めますが、いったんこの子を採用して個人開発進めます。
ということで。