はじめに
みなさん、こんにちは 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)
GitHub - jsonapi-serializer/jsonapi-serializer: A fast JSON:API serializer for Ruby (fork of Netflix/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
jsonapi-resources.com
んーよくわからん。
次。
エントリーNo 5 alba
名前かっこいい。笑
それに最高。
求めてた形で帰ってきた。
設定方法はこれを参照
【Rails】AlbaでAPI実装
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でした。
github.com
異論認めますが、いったんこの子を採用して個人開発進めます。
ということで。