Simplify Your Rails API Development with AMS
Tags: programming, rails, ruby, codenewbie
Published: 2023-05-03 15:29:20

## INTRODUCTION


In this post, I will share my experience using AMS in my fourth project for Flatiron School Software Engineering program. "Crime-Sleuths" is web blog application specially designed for individuals who have a keen interest in comprehending the truth and deciphering criminal behavior. It is also relevant for online crime detectives like me. I'll explain how I implemented Active Model Serializer in this project and demonstrate how it simplified the data serialization process, allowing me to focus on developing other features of the application. So, keep reading to discover the benefits of using AMS in your own projects.


---

## Define ActiveModel: :Serializer

Let's start by discussing Active Model Serializers or AMS, a powerful gem for Ruby on Rails that allows you to customize and simplify the formatting of our JSON output by allowing us to easily select the data we need and access relationships with just single request. With Active Model Serializers, you can create custom JSON output in an object-oriented way, giving you more control over the formatting and structure of your data.

To use Active Model Serializers, you first need to install the gem and create a serializer for your model. This serializer is a Ruby class that inherits from ActiveModel::Serializer and specifies which attributes should be included in the JSON output.

In your #Gemfile make sure to add:

```
gem 'active_model_serializers'
```

then Run _bundle install_

Next, you'll need to generate an ActiveModel::Serializer for your models, which can be easily done using the provided generator within the gem. To do so, simply open your console and run the following command:

```
rails g serializer <model name>
```
After running the command, a serializer file for the specified model will be created in the app/serializers directory. Active Model Serializers (AMS) offers a convention-based solution for serializing resources. MEANING that if we have a Post model, we can also have a corresponding PostSerializer serializer, and Rails will automatically use this serializer if we use the command render json: post in our controller.

Initially, in my _#app/controllers/post_controller.rb:_

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

This appears to be straightforward but what if we wished to display nested data involving users who own this posts. In such a case, we may need to incorporate a nested resource. For instance, in my blogging application as an example where users are the owners of posts. In this scenario, we may want to exhibit something like this:
_#app/controllers/post_controller.rb:_

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

Creating JSON strings can be a tedious and error-prone process. Additionally, this method does not adhere to the principle of separation of concerns, which is crucial in typical Rails applications. In such apps, the controller retrieves data from the model and passes it to the view layer, which is responsible for presenting the data to users. Similarly, in this case, it is not the controller's responsibility to determine how the data is returned. This is where ActiveModel::Serializer comes in handy.


---

## Serializing Associated Data

My blog app represents many-to-many relationship between three models: **Post, User, and Channel**.

In addition to the attributes, two associations are defined using the belongs_to macro: :user and :channel. These associations specify that the Post model has a foreign key relationship with both the User and Channel models.

When the PostSerializer is used to serialize a Post object, the serializer will automatically include the associated User and Channel objects in the serialized output. This means that the serialized JSON response will include the User and Channel objects in addition to the Post attributes.

This allows for easy retrieval of associated data without needing to make additional API calls or construct complex JSON objects manually.
_#app/controllers/post_serializer.rb:_  
![ps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whaly836gbffv61y2lu4.png)

Now in my _#app/controllers/post_controller.rb_ I can revert to its initial state:

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

---

## How to Implement Custom Serializers

When working with deeply nested models in Rails, it may be necessary to _explicitly_ customize the serialization of the data to ensure that only the necessary information is returned. In the example I provided, I customize serializer for the UserPostSerializer to render users and their posts in my Channel route. Additionally, I defined a short_content instance method to limit the content of the posts returned to the first 100 characters.
![up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwm1dtnihc8wl0j0uofp.png)
To include the custom serialization, the UserPostSerializer is specified in the has_many association for the posts in the ChannelSerializer. This guarantees that the serialized channel data includes the custom serialization defined in the UserPostSerializer for the post data. By explicitly setting the serializer for the association, developers can ensure that only the required data is returned in the desired format.
![cs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8hx21xyea1iaacsorzi6.png)

Now when you run the server _rails s_ and open browser to _http://localhost:3000/channels_, it should return:


![Ichannel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1l1gjgvtsvkqszr2lbg.jpg)

---

## CONCLUSION

I've found ActiveModel::Serializer to be a valuable tool for customizing the JSON data returned in my blog app project. It gave me the control to create serializers for specific resources and include only the data I need. AMS also follows Rails naming conventions made it intuitive to use.

Using the belongs_to and has_many macros in serializers, I was able to render associated data with ease. However, it's important to use these macros sparingly to avoid overwhelming the JSON data with excessive nesting.

It's worth noting that by default, AMS only nests associations one level deep in the serialized JSON. To go deeper, I used the include option to specify which associations to include.

Overall, ActiveModel::Serializer has helped me to customize the JSON data in my Rails application, ensuring that it's presented in the desired format.

## RESOURCES:
[Including Nested Association](https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/general/adapters.md#include-option)

[ActiveModel: :Serialization](https://api.rubyonrails.org/classes/ActiveModel/Serialization.html)