🐰
Rails で 複数の Serializer を組み合わせる
Rails で API を開発しています。
あるキーの値があるモデルを Serialize した結果であるようなレスポンスを返したいときの Serializer の実装につまづいたので、解決策を備忘録としてまとめます。
結論
- ActiveModelSerializers::SerializableResource.new を使う
やりたいことと前提
user_posts_controller.rb の show メソッドで、上述したようなレスポンスを返したい。
posts キーの中身は Post モデルが PostsSerializer によって Serialize された配列を返したい。
また、すでに PostsSerializer は実装されており、別の Controller で使用されている。
posts キー以外は User モデルの attribute となっており、posts と同一の階層で返したい[1]。
このとき、User を Serialize し、さらに Posts も Serialize する必要があります。
User モデルと Post モデルは同一階層に位置しているため、Serializer をネストする必要があり、その方法がわからず困ってました。
{
"name": "なまえ",
"age": 24,
"address": "----",
"posts": [
// Post モデルが、PostsSerializer によって Serialize されたやつの配列
// (省略)
]
}
解決策
Serializer 内で、Serializer を呼び出せるのでそのようなメソッドを定義する
user_posts_controller.rb
def show
# データを取得する処理は省略する
results = { user: user, posts: posts }
render json: results, serializer: UserPostsSerializer
end
user_posts_serializer.rb
class UserPostsSerializer < ActiveModel::Serializer
attribute :name, :age, :address
attribute :posts
def name
object[:user][:name]
end
def age
object[:user][:age]
end
def address
object[:user][:address]
end
def posts
ActiveModelSerializers::SerializableResource.new(
object[:posts], each_serializer: PostsSerializer
).as_json
end
end
さいごに
他によりよい方法があればご指摘いただけますと幸いです。
-
user キーを使ってネストさせた方がいいと思いますが、Serializer の数が増えてしまうので、簡略化のために同一階層としています。 ↩︎
Discussion