Rails Serialization (Active Model Serializer)
Ruby on Rails is a great choice for an API specifically because rendering JSON is as easy as render :json
. However, out of the box, Rails serves up some pretty ugly data. The result of this is much messy.
Moreover if you want to deal with the associations you’ve already defined for your introduced models, it will become a cause of headache for you.
But luckily, Rails provides some gems to handle all this. Just install any of them, define what you want to get rendered, and all the headache is for the gem. Among multiple available options, we will go for Active Model Serializer
.
Add this in your Gemfile
gem 'active_model_serializers'
and run bundle install.
Now, when the gem is installed, you need to run a command to generate your serializer. Suppose I want to generate a serializer for my Project model, I’ll run run this command in the terminal:
rails g serializer project
This will create a file named proejct_serializer.rb
under the app/serializers directory. Move to the file and introduce the attributes you want to be include in serialization. Suppose I just want to add id
and title
attributes of project while serializing. I’ll put the following code inside the file:
class ProjectSerializer < ActiveModel::Serializer attributes :id, :titleend
Now move to the project_controller.rb
and look for, suppose, show
action. When you done with finding the right project
to show, you can render it using just the following line
render json: project
This will render your project which looks much pretty like this:
{ "project": { "id": 10, "title": "First Project" }}
Now, suppose you want to list the author of the project too. For this, yyou need to create a serializer for your author (‘user’ in my case) model by running the following command and tell the serializer which attributes of user you want (I allowed user id and email to be listed).
rails g serializer user
Now its time to tell your project serializer to include its author (user) too. For this, add a line in your project_serializer so it look like this
class ProjectSerializer < ActiveModel::Serializer attributes :id, :title has_one :userend
Now if you hit your api again, the following JSON will be rendered as a result:
{ "project": { "id": 10, "title": "First Project", "user": { "id": 1, "email": "wajeehahsan9@gmail.com" } }}
We’re DONE with serialization part but keep in mind these two things:
1- Serializers are only concerned with multiplicity, and not ownership. belongs_to
ActiveRecord associations can be included using has_one
in your serializer like we did for project_serializer
. For has_many
association, use has_many
.
2- You can’t have two serializers that has_many
/ has_one
each other. Like in our case, each project has_one user (to implement belongs_to association) but we didn’t introduced has_many :projects
in our user_serializer
though each user has_many projects in our schema. Otherwise it’ll cause stuck with an error like:
SystemStackError (stack level too deep)
Because project_serializer
will start referring to user_serializer
and user_serializer
will refer back to project_serializer
and it will stuck in an infinite loop.