{"id":17730,"date":"2021-04-19T10:38:00","date_gmt":"2021-04-19T10:38:00","guid":{"rendered":"https:\/\/www.bacancytechnology.com\/blog\/?p=17730"},"modified":"2026-02-24T11:11:24","modified_gmt":"2026-02-24T11:11:24","slug":"active-model-serializers-with-rails-api","status":"publish","type":"post","link":"https:\/\/www.bacancytechnology.com\/blog\/active-model-serializers-with-rails-api","title":{"rendered":"How to Implement Active Model Serializers with Rails API?"},"content":{"rendered":"<p style=\"color:#FFA500;margin-bottom: 7px;\"><strong><i>Quick Summary:<\/i><\/strong><\/p>\n<p><i><strong>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.<\/strong><\/i><\/p>\n<h2>What is Active Model Serializers?<\/h2>\n<p>Serializer gem allows us to format our JSON easily. It will enable us to select only the data we want and access our relationships with a single request. <b>Active Model Serializers<\/b> provides a way of creating custom JSON in an object-oriented manner.<\/p>\n<p>Active Model Serializer  consists of two components:<\/p>\n<ul class=\"bullets text-left\">\n<li><strong>Serializers:<\/strong> It describes which attributes &#038; relationships to be serialized.<\/li>\n<li><strong>Adapters:<\/strong> It describes the way of serializing those attributes &#038; relationships, i.e., how to serialize.<\/li>\n<\/ul>\n<p>The serializer creates the relationship in the backend and then translates it to the frontend.<\/p>\n<h2>Importance and Usage of Active Model Serializers<\/h2>\n<p>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.<\/p>\n<p>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.<\/p>\n<h2>Active Model Serializers Tutorial: How to Implement Active Model Serializers with Rails API?<\/h2>\n<p>Here is the step-by-step guide to implementing Active Model Serializers with Rails API whose source code is available in the <a href=\"https:\/\/github.com\/bhavik2936\/active-model-serializer\" target=\"_blank\" rel=\"noopener\"><strong><i>Github repository<\/i><\/strong><\/a>.<\/p>\n<ul class=\"bullets text-left\">\n<li><i>active_model_serializers gem<\/i><\/li>\n<p>To achieve the intention of serialization<\/p>\n<ul class=\"bullets text-left\">\n<li><i>faker gem<\/i><\/li>\n<p>To mock (fill) data<\/p>\n<p>Let\u2019s get started with building our demo project for Active Model Serializer.<\/p>\n<h3><u>1. Create new project<\/u><\/h3>\n<p>Create a new project by executing the below-mentioned command<\/p>\n<pre>rails new active-model-serializer --api<\/pre>\n<h3><u>2. Adding Gem<\/u><\/h3>\n<p>Add below gems in your <i>Gemfile<\/i><\/p>\n<ul class=\"bullets text-left\">\n<li><i>active_model_serializers<\/i><\/li>\n<li><i>rack-cors<\/i><\/li>\n<li><i>faker <b>(development &#038; test environment only)<\/b><\/i><\/li>\n<\/ul>\n<p>Install these newly added gems using this command<\/p>\n<pre>$ bundle install<\/pre>\n<h3><u>3. Data Modeling<\/u><\/h3>\n<p>Firstly, we will create two models and connect them to One-to-Many relationships.<\/p>\n<p>We\u2019ve built an Employee model having attributes <i>(name, email, date_of_birth, mobile_no, designation, salary)<\/i>. Which belongs_to<i> Manager<\/i> model having the attribute <i>(name)<\/i>.<\/p>\n<pre>$ rails g model Manager name\r\n$ rails g model Employee name email dob:date mobile\r\ndesignation salary:number manager:references<\/pre>\n<p>The <i>Manager has_many employees<\/i>. At the same time, <i>Employee belongs_to only one manager<\/i>.<\/p>\n<h3><u>4. Perform Migration<\/u><\/h3>\n<p>After the model changes, migration is necessary. Run the below command<\/p>\n<pre>$ rails db:migrate<\/pre>\n<h3><u>5. Configuration of Routes<\/u><\/h3>\n<p>We will now add routes for APIs-only methods. The routes can extend with other versioning.<\/p>\n<p><b># config\/routes.rb<\/b><\/p>\n<pre>Rails.application.routes.draw do\r\n  concern :api_base do\r\n    resources :employees   \r\n    resources :managers\r\n  end\r\n\r\n  namespace :v1 do\r\n    concerns :api_base\r\n  end\r\nend\r\n<\/pre>\n<h3><u>6. Pre-defined Data Added<\/u><\/h3>\n<p>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.<\/p>\n<pre>$ rails db:seed<\/pre>\n<p>Here\u2019s the <i>seeds.rb<\/i><\/p>\n<p><b># db\/seeds.rb<\/b><\/p>\n<pre>Employee.destroy_all\r\nManager.destroy_all\r\n\r\nmanagers = (1..20).map do\r\n  Manager.create!(\r\n    name: \"manager\"\r\n  )\r\nend\r\n\r\nemployee = (1..50).map do\r\n  Employee.create!(\r\n    name: \"employee\",\r\n    email: \"emp@gmail.com\",\r\n    dob: \"17-01-1988\",\r\n    mobile: \"8879544321\",\r\n    designation: \"Senior Developer\",\r\n    salary: 35_000,\r\n    manager: managers.sample\r\n  )\r\nend\r\n<\/pre>\n<h3><u>7. Define Model Serializer<\/u><\/h3>\n<p>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.<\/p>\n<p>You can see the below example for the model serializer.<\/p>\n<p><b># app\/serializers\/v1\/employee_serializer.rb<\/b><\/p>\n<pre>module V1\r\n  class EmployeeSerializer < ActiveModel::Serializer\r\n    attributes :id, :name, :email, :designation, :manager\r\n\r\n    def manager\r\n      {\r\n        id: object.manager.id,\r\n        name: object.manager.name\r\n      }\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p><b># app\/serializers\/v1\/manager_serializer.rb<\/b><\/p>\n<pre>module V1\r\n  class ManagerSerializer < ActiveModel::Serializer\r\n    attributes :id, :name, :employees\r\n\r\n    def employees\r\n      object.employees.map do |employee|\r\n        {\r\n          id: employee.id,\r\n          name: employee.name,\r\n          email: employee.email,\r\n          designation: employee.designation\r\n        }\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<h3><u>8. Define Controller<\/u><\/h3>\n<p>It\u2019s 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.<\/p>\n<p>You can see the below example for controllers.<\/p>\n<p><b># app\/controllers\/v1\/employees_controller.rb<\/b><\/p>\n<pre>module V1\r\n  class EmployeesController < ApplicationController\r\n\r\n    def index\r\n      employees = Employee.all.includes(:manager)  \r\n\/\/ used includes method to prevent N-Query problem\r\n      \r\n      render json: {\r\n        data: ActiveModelSerializers::SerializableResource.new(employees, each_serializer: EmployeeSerializer),\r\n        message: ['Employee list fetched successfully'],\r\n        status: 200,\r\n        type: 'Success'\r\n      }\r\n    end\r\n\r\n    def show\r\n      employee = Employee.find(params[:id])\r\n      \r\n      render json: {\r\n        data: ActiveModelSerializers::SerializableResource.new(employee, serializer: EmployeeSerializer),\r\n        message: ['Employee profile fetched successfully'],\r\n        status: 200,\r\n        type: 'Success'\r\n      }\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p><b># app\/controllers\/v1\/managers_controller.rb<\/b><\/p>\n<pre>module V1\r\n  class ManagersController < ApplicationController\r\n    def index\r\n      managers = Manager.all.includes(:employees)\r\n      \r\n      render json: {\r\n        data: ActiveModelSerializers::SerializableResource.new(managers, each_serializer: ManagerSerializer),\r\n        message: ['Manager list fetched successfully'],\r\n        status: 200,\r\n        type: 'Success'\r\n      }\r\n    end\r\n\r\n    def show\r\n      manager = Manager.find(params[:id])\r\n      \r\n      render json: {\r\n        data: ActiveModelSerializers::SerializableResource.new(manager, serializer: ManagerSerializer),\r\n        message: ['Manager profile fetched successfully'],\r\n        status: 200,\r\n        type: 'Success'\r\n      }\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<h3><u>9. End-point Response<\/u><\/h3>\n<p>The output for the request to fetch details of employees and managers APIs is as shown below.<\/p>\n<p><b>\/\/ GET http:\/\/localhost:3000\/v1\/employees\/1<\/b><\/p>\n<pre>\r\n        {\r\n\t  \"data\":{\r\n\t    \"id\":1,\r\n\t    \"name\":\"employee\",\r\n\t    \"email\":\"emp@gmail.com\",\r\n\t    \"designation\":\"Senior Developer\",\r\n\t    \"manager\":{\r\n\t      \"id\":6,\r\n\t      \"name\":\"manager\"\r\n\t    }\r\n\t  },\r\n\t  \"message\":[\r\n\t    \"Employee profile fetched successfully\"\r\n\t  ],\r\n          \"status\":200,\r\n\t  \"type\":\"Success\"\r\n\t}\r\n\r\n<\/pre>\n<p><b>\/\/ GET http:\/\/localhost:3000\/v1\/managers\/6<\/b><\/p>\n<pre>\r\n        {\r\n\t  \"data\":{\r\n\t    \"id\":6,\r\n\t    \"name\":\"manager\",\r\n\t    \"employees\":[\r\n\t      {\r\n\t        \"id\":1,\r\n\t        \"name\":\"employee\",\r\n\t        \"email\":\"emp@gmail.com\",\r\n\t        \"designation\":\"Senior Developer\"\r\n\t      },\r\n\t      {\r\n\t        \"id\":33,\r\n\t        \"name\":\"employee\",\r\n\t        \"email\":\"emp@gmail.com\",\r\n\t        \"designation\":\"Senior Developer\"\r\n\t      },\r\n\t      {\r\n\t        \"id\":39,\r\n\t        \"name\":\"employee\",\r\n\t        \"email\":\"emp@gmail.com\",\r\n\t        \"designation\":\"Senior Developer\"\r\n\t      }\r\n\t    ]\r\n\t  },\r\n\t  \"message\":[\r\n\t    \"Manager profile fetched successfully\"\r\n\t  ],\r\n\t  \"status\":200,\r\n\t  \"type\":\"Success\"\r\n\t}\r\n<\/pre>\n<h3><u>10. Versioning Controller & Serializer<\/u><\/h3>\n<p>We can extend the API and serializers by versioning them.<br \/>\nFor creating another version of the controller, create it under the path <i>app\/controllers\/v2\/employees_controller.rb<\/i><\/p>\n<p>And for creating the serializer, create it under the path <i>app\/serializers\/v2\/employee_serializer.rb<\/i>.<\/p>\n<p>Remember that the class you\u2019re creating for versioned API should fall under<i> module V2<\/i> (or whatever version you\u2019re defining for).<\/p>\n<p><i><b>Here is the list of steps we performed to build serializer APIs:<\/b><\/i><\/p>\n<ul class=\"bullets text-left\">\n<li>Created new project using <i>rails new active-model-serializer --api<\/i><\/li>\n<li>Added required gems<\/li>\n<li>Defined models<\/li>\n<li>Migrated the schema<\/li>\n<li>Configured routes for the API<\/li>\n<li>Defined serializer for the respective model<\/li>\n<li>Implemented business logic in the controller<\/li>\n<li>Fetched data from API endpoints<\/li>\n<\/ul>\n<p>You might like to know: <a href=\"https:\/\/www.bacancytechnology.com\/blog\/ruby-on-rails-maintenance-cost\" target=\"_blank\" rel=\"noopener\">How to Reduce Ruby on Rails Maintenance Cost?<\/a><\/p>\n<h2>Alternative of Active Model Serializers<\/h2>\n<ul class=\"bullets text-left\">\n<li><a href=\"http:\/\/jsonapi-rb.org\/\" target=\"_blank\" rel=\"noopener\"><strong><strong>JSONAPI-RB<\/strong><\/strong><\/a>- It is considered a highly performant and modular JSON:API. There's a vibrant community around it that has produced this Ruby library consisting of four micro-libraries and two frameworks.<\/li>\n<li><a href=\"https:\/\/github.com\/Netflix\/fast_jsonapi\" target=\"_blank\" rel=\"noopener\"><i><strong>Fast JSON API<\/strong><\/i><\/a>- It is a lightning-fast JSON:API serializer for Ruby Objects. It is believed to be 25 times faster than Active Model Serializers.<\/li>\n<li><a href=\"https:\/\/github.com\/procore\/blueprinter\" target=\"_blank\" rel=\"noopener\"><i><strong>Blueprinter<\/strong><\/i><\/a>- It is a high-speed, declarative, and API agnostic serializer that uses composable views for reducing duplication.<\/li>\n<\/ul>\n<h2 id=\"5\">Conclusion<\/h2>\n<p>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\u2019ve landed on the right page. Get in touch with us to <a href=\"https:\/\/www.bacancytechnology.com\/ruby-on-rails-development\">hire ROR developer<\/a><\/a> with the desired skillset at your ease and convenience.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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. What is Active Model Serializers? Serializer gem allows us to format our JSON [&hellip;]<\/p>\n","protected":false},"author":47,"featured_media":17735,"comment_status":"open","ping_status":"open","sticky":false,"template":"blog-new-template.php","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_lmt_disableupdate":"no","_lmt_disable":"no","footnotes":""},"categories":[35],"tags":[],"coauthors":[1644],"class_list":["post-17730","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruby-on-rails"],"acf":[],"modified_by":"Nisarg Bhavsar","_links":{"self":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts\/17730","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/users\/47"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/comments?post=17730"}],"version-history":[{"count":1,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts\/17730\/revisions"}],"predecessor-version":[{"id":57896,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/posts\/17730\/revisions\/57896"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/media\/17735"}],"wp:attachment":[{"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/media?parent=17730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/categories?post=17730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/tags?post=17730"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/blog\/wp-json\/wp\/v2\/coauthors?post=17730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}