Ruby Serializer in Action

Clark Johnson
2 min readApr 20, 2020

--

Ruby has been in use now for quite a while. Even though that is the case, there is still a need to address well-used issues. In this particular case, I am talking about active serializer.

One of the most important steps in developing a JSON API using Ruby on Rails is serializing the rendered JSON. That means structuring the data and selecting the attributes from the model.

Let’s look at an example of a basic route:/users . This route is intended to serve an array of objects containing data for all users in the database. In the users_controller.rb file you would find a method that looks like this:

def index
render json: @users
end

That short and simple method will serve a JSON array containing what we expect. However, it will contain every available attribute from the user's table: id, name, email, created_at, and updated_at.

[
{
"id": 3,
"email": "sigurd.cain@example.org",
"name": "Prak",
"created_at": "2020-04-20T02:45:00.906Z",
"updated_at": "2020-04-20T02:45:00.906Z"
},
{
"id": 4,
"email": "providenci@example.org",
"name": "Willam",
"created_at": "2020-04-20T02:45:00.909Z",
"updated_at": "2020-04-20T02:45:00.909Z"
}
]

Some of these attributes are fine, but some we don’t want to serve. We don’t actually want to include the user’s id in the response. And we may not want to include both the created_at and updated_at fields.

Serializer: to_json

To properly format the response, the serializer comes in to play.

def index
@users = User.all
render json: @users.to_json(only: [:email, :name])
end

Let’s take a look at the result:

[
{
"email": "sigurd.cain@example.org",
"name": "Prak"
},
{
"email": "providenci@example.org",
"name": "Willam"
}
]

Just like that, by employing the to_json serializer, we’ve cleaned up the data. The only option specifies which attributes will actually be included.

Option: methods

Another important option to consider is methods . When the class for the model in use contains methods whose returned values you want to be included in the rendered data, this is the option that gets it done.

Let’s say this user has ratings associated with a separate table. The average for those ratings is available as an instance method on the model.

def average_rating
if self.ratings.count > 0
self.ratings.map { |r| r.rating }.sum / self.ratings.count
else
1
end
end

To include this value in the rendered output, call on themethods option.

render json: @users.to_json(only: [:email, :name], methods: :average_rating)

This will include the data and produce the desired output.

[
{
"email": "sigurd.cain@example.org",
"name": "Prak",
"average_rating": 3
},
{

"email": "providenci@example.org",
"name": "Willam",
"average_rating": 4
}
]

By utilizing these built-in simple techniques, the JSON output can be formatted as necessary without calling on external gems.

Happy coding!

--

--

Clark Johnson

Full stack software engineer seeking projects using React, Ruby on Rails, Javascript, when I’m not at a baseball game