Rails: Switches Serializer according to STI Type
Tags: rails, ruby, programming
Published: 2024-05-28 14:00:00

## Introduction

Hello, here is Tamura.

Suppose you have model data of multiple types using STI and want to mix and return them in a single API endpoint. In this case, you would like to switch the serializer according to the STI type.

In this article, I will show you how to do this.

## Issue
Suppose the following class hierarchy is realized in STI

![class hierarchy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1atef26vj3kexvvww3m.png)

SimplePosts has a `title` and `body` field, and QAPosts has a `question` and `answer` field. They all have a common `posted_at` field.

Suppose you define an API endpoint called `/api/v1/posts` and want to return JSON as follows:

![return JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6i6d5im346krq9eo0qzc.png)

Depending on whether the Posts type is `SimplePost` or `QAPost`, the JSON keys will differ.

If you are using ActiveModel::Serializers to output JSON, you will need to switch the Serializer depending on the type of Posts.

## Solution

The code is shown below.

**app/serializers/post_serializer.rb**

![post_serializer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g14q3vc88pbozdvdlz0o.png)

**app/serializers/simple_post_serializer.rb**

![simple_post_serializer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuciktzassr8hrblna11.png)

**app/serializers/qa_post_serializer.rb**

![qa_post_serializer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no6vef0wvzvpxa2tn9ag.png)

**app/controllers/api/v1/posts_controller.rb**

![posts_controller](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lrlol2bqtumqrsu4156.png)

Override the `attributes` method in PostSerializer. Since each data is taken as an `object`, the class is determined in case, and `SimplePostSerializer.new(object).attributes(nil, reload)` and `QAPostSerializer.new(object).attributes( nil, reload)` generates attributes and merges them into `@attributes`.

**Reference**: https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L334-L343

The reason for overriding the `json_key` method is to display `posts` in the json toplevel object. If this is not defined, `qa_posts` and the type first processed by the Serializer will be set as the key, as shown below.

![set as the key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4yw8nofhixm5gf7ec8l.png)

Note that if `jsonapi_include_toplevel_object` is `false`, there is no need to override the `json_key` method.

**Reference**: https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L384-L392

---
## About Us💡
In addition, I want to introduce a little more about GROWI, an open software developed by us **WESEEK, Inc**.

**GROWI** is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including **LDAP/OAuth/SAML**.

**GROWI** originated in Japan and GROWI OSS is **FREE** for anyone to [download](https://docs.growi.org/en/admin-guide/?utm_source=dev+community&utm_medium=referral&utm_campaign=Rails_Switches_Serializer_according_to_STI_Type) and use **in English**.

For more information, go to [GROWI.org](https://growi.org/en/?utm_source=dev+community&utm_medium=referral&utm_campaign=Rails_Switches_Serializer_according_to_STI_Type) to learn more about us. You can also follow our [Facebook](https://www.facebook.com/people/GROWIcloud/100089272547238/) to see updates about our service.

![GROWI.org](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rhpa0qcdukeall2vfsj.png)