Quick Summary:
This blog covers insights into Active Model Serializers, their benefits, and their usage. In this tutorial, we will learn how to make serializers for Rails APIs and implement them efficiently so that they can be accommodated to versioning APIs too.
Table of Contents
Active Model Serializer consists of two components:
The serializer creates the relationship in the backend and then translates it to the frontend.
Active Model Serializers offers a way to create custom JSON by representing each resource as a class inherited from Active Model Serializers. With the help of a serializer, we need to make a single request to the backend. With proper association done through serialization, the backend will fetch all the required data needed by request rather than requesting multiple times to multiple models.
The primary usage of Active Model Serializers is to create custom JSON responses. By default, Rails provides a way to render JSON, but we need a serializer if we want to customize it.
Here is the step-by-step guide to implementing Active Model Serializers with Rails API whose source code is available in the Github repository.
In this demo, we will be installing two dependencies-
To achieve the intention of serialization
To mock (fill) data
Let’s get started with building our demo project for Active Model Serializer.
Create a new project by executing the below-mentioned command
rails new active-model-serializer --api
Add below gems in your Gemfile
Install these newly added gems using this command
$ bundle install
Firstly, we will create two models and connect them to One-to-Many relationships.
We’ve built an Employee model having attributes (name, email, date_of_birth, mobile_no, designation, salary). Which belongs_to Manager model having the attribute (name).
$ rails g model Manager name $ rails g model Employee name email dob:date mobile designation salary:number manager:references
The Manager has_many employees. At the same time, Employee belongs_to only one manager.
After the model changes, migration is necessary. Run the below command.
$ rails db:migrate
We will now add routes for APIs-only methods. The routes can extend with other versioning.
# config/routes.rb
Rails.application.routes.draw do
concern :api_base do
resources :employees
resources :managers
end
namespace :v1 do
concerns :api_base
end
end
Declare data seed file to insert mock data for defined models. We can also enter data manually into the database, but it is easy with the seed file by running a single command.
$ rails db:seed
Here’s the seeds.rb
# db/seeds.rb
Employee.destroy_all
Manager.destroy_all
managers = (1..20).map do
Manager.create!(
name: "manager"
)
end
employee = (1..50).map do
Employee.create!(
name: "employee",
email: "emp@gmail.com",
dob: "17-01-1988",
mobile: "8879544321",
designation: "Senior Developer",
salary: 35_000,
manager: managers.sample
)
end
We will define a serializer for each model indicating what data to be broadcasted over the network by serializing the model. The attribute we declared to be serialized can be further defined to explain what data to be passed for.
You can see the below example for the model serializer.
# app/serializers/v1/employee_serializer.rb
module V1
class EmployeeSerializer < ActiveModel::Serializer
attributes :id, :name, :email, :designation, :manager
def manager
{
id: object.manager.id,
name: object.manager.name
}
end
end
end
# app/serializers/v1/manager_serializer.rb
module V1
class ManagerSerializer < ActiveModel::Serializer
attributes :id, :name, :employees
def employees
object.employees.map do |employee|
{
id: employee.id,
name: employee.name,
email: employee.email,
designation: employee.designation
}
end
end
end
end
It’s time to define the controller for respective models to serve serialized objects over API by explicitly defining serializers for individual models. Here, we will define which serializer will be used for passing data by JSON.
You can see the below example for controllers.
# app/controllers/v1/employees_controller.rb
module V1
class EmployeesController < ApplicationController
def index
employees = Employee.all.includes(:manager)
// used includes method to prevent N-Query problem
render json: {
data: ActiveModelSerializers::SerializableResource.new(employees, each_serializer: EmployeeSerializer),
message: ['Employee list fetched successfully'],
status: 200,
type: 'Success'
}
end
def show
employee = Employee.find(params[:id])
render json: {
data: ActiveModelSerializers::SerializableResource.new(employee, serializer: EmployeeSerializer),
message: ['Employee profile fetched successfully'],
status: 200,
type: 'Success'
}
end
end
end
# app/controllers/v1/managers_controller.rb
module V1
class ManagersController < ApplicationController
def index
managers = Manager.all.includes(:employees)
render json: {
data: ActiveModelSerializers::SerializableResource.new(managers, each_serializer: ManagerSerializer),
message: ['Manager list fetched successfully'],
status: 200,
type: 'Success'
}
end
def show
manager = Manager.find(params[:id])
render json: {
data: ActiveModelSerializers::SerializableResource.new(manager, serializer: ManagerSerializer),
message: ['Manager profile fetched successfully'],
status: 200,
type: 'Success'
}
end
end
end
The output for the request to fetch details of employees and managers APIs is as shown below.
// GET http://localhost:3000/v1/employees/1
{
"data":{
"id":1,
"name":"employee",
"email":"emp@gmail.com",
"designation":"Senior Developer",
"manager":{
"id":6,
"name":"manager"
}
},
"message":[
"Employee profile fetched successfully"
],
"status":200,
"type":"Success"
}
// GET http://localhost:3000/v1/managers/6
{
"data":{
"id":6,
"name":"manager",
"employees":[
{
"id":1,
"name":"employee",
"email":"emp@gmail.com",
"designation":"Senior Developer"
},
{
"id":33,
"name":"employee",
"email":"emp@gmail.com",
"designation":"Senior Developer"
},
{
"id":39,
"name":"employee",
"email":"emp@gmail.com",
"designation":"Senior Developer"
}
]
},
"message":[
"Manager profile fetched successfully"
],
"status":200,
"type":"Success"
}
We can extend the API and serializers by versioning them.
For creating another version of the controller, create it under the path app/controllers/v2/employees_controller.rb
And for creating the serializer, create it under the path app/serializers/v2/employee_serializer.rb.
Remember that the class you’re creating for versioned API should fall under module V2 (or whatever version you’re defining for).
Here is the list of steps we performed to build serializer APIs:
Partner with a trusted Ruby on Rails Development Company to build high-performance applications.
So, We hope you have a clear understanding of What is Active Model Serializers? Implementation, Usage, and Alternatives of Active Model Serializers in Rails 6. If you are looking for a helping hand in your Ruby on Rails project, then you’ve landed on the right page. Get in touch with us to hire ROR developer with the desired skillset at your ease and convenience.
Your Success Is Guaranteed !
We accelerate the release of digital product and guaranteed their success
We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.