Blogpost cover michal brodecki1 2x 2

Building APIs using Ruby on Rails is a very common practice. As backend developers we need to properly send responses from the server, sometimes containing long and complex data structures. I can’t imagine creating a response without the ActiveModel::Serializer gem 

It will help you build a proper data structure and maintain code readability. In this post, I will guide you through the common and uncommon uses of this gem.

Installation and use

Installation is very straightforward. Just add the gem to your Gemfile and run bundle.

gem 'active_model_serializers'

That’s all.

What can I do with it? Let’s assume we have a User model with email and name fields. We want to serialize the object. How can we do it? Serializers are kept in app/models/serializers. To generate one, you can use a generator or create it manually.

rails g serializer user

This is what has been generated:

class UserSerializer < ActiveModel::Serializer
  attributes :id
end

It looks very similar to a model declaration. To test it you just need to render a JSON object in the controller.

def show
  @user = User.find(params[:id])
  render json: @user
end

The serializer will know that it needs to use the UserSerializer for that object. To add custom attributes you need to insert them into the attributes line:

attributes :id, :name, :email

You can create your own attribute names. But remember to define them, because the serializer will look for them in the model you are trying to serialize.

attributes :id, :name, :email, :full_info

def full_info
 "#{object.email} #{object.name}"
end

As you can see, object is treated just like self in models. So, basically, you can override any attribute you want.

To have a nested array structure in your serialized response you need to add:

has_many :posts

If your object has this relation it will automatically look for the serializer in the serializers folder and apply it. Of course, you can define your own way of displaying it by adding a method with the same name.

has_many :posts

def posts
  object.posts.published
end

Another useful trick is to define your own serializers. To do so, simply pass the name of the serializer like this:

def show
  @user = User.find(params[:id])
  render json: @user, serializer: MyOwnSerializer
end

Additionally, you can assign custom serializers inside the serializer itself. It can be done like this (notice that each_serializer method has to be added when it's a collection):

has_many :posts, each_serializer: MySuperSerializer
belongs_to :account, serializer: SuperAccountSerializer

However, it is not possible to assign serializers inside the methods you define.

Sometimes you want to serialize an object without rendering it. Fortunately, there is a method for that:

my_serialized_object = ActiveModelSerializers::SerializableResource.new(@post, options).as_json

This way you have serialized the post under my_serialized_object variable.

Sometimes you want to get rid of the root name. You can disable it by passing root: false.

def show
  @user = User.find(params[:id])
  render json: @user, serializer: MyOwnSerializer, root: false
end

You can also pass some extra values into a serialized hash using the meta keyword.

def show
  @user = User.find(params[:id])
  render json: @user, serializer: MyOwnSerializer, meta: {your hash or value}, meta_key: :some_key
end

The only thing you have to remember is to have a root key when using meta. Otherwise, it won’t work.

Summary

There are a few more options that serializers give you. The only issue I struggle with is that there are some incompatibilities between older and newer versions. Thankfully, authors are working hard to overcome this problem. I strongly recommend reading the Readme on the gem's Github page. Feel free to leave a comment or question. I will be happy to answer and help you.

Post tags:

Join our awesome team
Check offers

Work
with us

Tell us about your idea
and we will find a way
to make it happen.

Get estimate