Skip to main content Link Search Menu Expand Document (external link)

Serializer

On the previous page, we demonstrated how to design an API similar to PSGC (Philippine Standard Geographic Code). This API will now be used by our serializer.

In this topic, we will choose only the data we want to see/view of the user, with a single request.

Table of contents

  1. Why we use Serializer?
  2. How to Install Serializer?
  3. Region Serializer
  4. Province Serializer
  5. City Serializer
  6. Barangay Serializer

Why we use Serializer?

Serializer essentially provides an easy way to customize how the JSON is rendered by our controllers.

Advantages

The Serializer allows us to:

  • refactor code to avoid repetition
  • render numerous data models from a single controller
  • specify which attributes to render

How to Install Serializer?

Reminder:

Make sure that your containers are up and running.

In your gemfile, add gem active_model_serializers.

gem 'active_model_serializers'

Then run bundle install.

 root@0122:/usr/src/app# bundle install
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
...
Installing active_model_serializer 0.10.2
Bundle complete! 10 Gemfile dependencies, 80 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Region Serializer

Generate region serializer with rails g serializer region.

 root@0122:/usr/src/app# rails g serializer region
      create  app/serializers/region_serializer.rb                                                           

This will create a file named region_serializer.rb under the app/serializers directory. Move to the file and introduce the attributes you want to be include in serialization. Suppose we just want to add name and id attributes of project while serializing.

Now we create a serializer called RegionSerializer.

# app/serializer/region_serializer.rb

class RegionSerializer < ActiveModel::Serializer
  attributes :id, :name
end

The attributes is used to choose a specific column in the table that you want to render in controller and the other column is hidden.

In the app/controllers/api/v1, after we collect the attributes in RegionSerializer, add the RegionSerializer to our regions_controller.rb like this:

# app/controllers/api/v1/regions_controller.rb

class Api::V1::RegionsController < ApplicationController

  def index
    regions = Address::Region.all
-   render json : regions
+   render json : regions, each_serializer: RegionSerializer
  end

  def show
    region = Address::Region.find(params[:id])
-   render json : region
+   render json : region, serializer: RegionSerializer
  end
end

The different of each_serializer and serializer The each_serializer when you have a collection of records, such as regions, provinces, cities, barangays you have to iterate over each resource to get a serialized collection of records and the serializer when you have a single record such as region, province, city, barangay no iteration is required, and in return you get a single serialized resource.

This is the differences of with and without serializer

Without Serializer

http://localhost:3000/api/v1/regions

[
    {
      "id": 1,
      "code": "010000000",
      "name": "Region I",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2,
      "code": "020000000",
      "name": "Region II",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    }, 
    # ...
]

http://localhost:3000/api/v1/regions/1

    {
      "id": 1,
      "code": "010000000",
      "name": "Region I",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    }

With Serializer

http://localhost:3000/api/v1/regions

[
    {
      "id": 1,
      "name": "Region I"
    },
    {
      "id": 2,
      "name": "Region II"
    }, 
    # ...
]

http://localhost:3000/api/v1/regions/1

    {
      "id": 1,
      "name": "Region I"
    }

Now, the result of with serializer it see more clearly and easily understood the output of JSON format, than without serializer. The other column is now hidden.

Province Serializer

Generate province serializer with rails g serializer province.

 root@0122:/usr/src/app# rails g serializer province
      create  app/serializers/province_serializer.rb                                                           

This will create a file named province_serializer.rb under the app/serializers directory. Move to the file and introduce the attributes you want to be include in serialization. Suppose we just want to add name, region and id attributes of project while serializing.

Now we create a serializer called ProvinceSerializer.

# app/serializer/province_serializer.rb

class ProvinceSerializer < ActiveModel::Serializer
  attributes :id, :region, :name

  def region
    object.region.name
  end
end

You can also add custom attributes to change the return value of the attributes depending on what value you need to show.

In the app/controllers/api/v1, after we collect the attributes in ProvinceSerializer, add the ProvinceSerializer to our provinces_controller.rb like this:

# app/controllers/api/v1/provinces_controller.rb

class Api::V1::ProvincesController < ApplicationController

  def index
    region = Address::Region.find_by_id(params[:region_id])
    provinces = if region
                  region.provinces
                else
                  Address::Province.all
                end

-   render json: provinces
+   render json: provinces, each_serializer: ProvinceSerializer
  end

  def show
    province = Address::Province.find_by_id(params[:id])
-   render json: province
+   render json: province, serializer: ProvinceSerializer
  end
end

This is the differences of with and without serializer

Without Serializer

http://localhost:3000/api/v1/regions/1/provinces

[
    {
      "id": 1,
      "region_id": 1,
      "code": "012800000",
      "name": "Ilocos Norte",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2,
      "region_id": 1,
      "code": "012900000",
      "name": "Ilocos Sur",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    #...
]

http://localhost:3000/api/v1/provinces

[
    {
      "id": 1,
      "region_id": 1,
      "code": "012800000",
      "name": "Ilocos Norte",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2,
      "region_id": 1,
      "code": "012900000",
      "name": "Ilocos Sur",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    #...
]

http://localhost:3000/api/v1/provinces/1

{
  "id": 1,
  "region_id": 1,
  "code": "012800000",
  "name": "Ilocos Norte",
  "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
  "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
}

With Serializer

http://localhost:3000/api/v1/regions/1/provinces

[
    {
      "id": 1,
      "region": "Region I",
      "name": "Ilocos Norte"
    },
    {
      "id": 2,
      "region": "Region I",
      "name": "Ilocos Sur"
    },
    #...
  ]

http://localhost:3000/api/v1/provinces

[
    {
      "id": 1,
      "region": "Region I",
      "name": "Ilocos Norte"
    },
    {
      "id": 2,
      "region": "Region I",
      "name": "Ilocos Sur"
    },
    #...
]

http://localhost:3000/api/v1/provinces/1

{
    "id": 1,
    "region": "Region I",
    "name": "Ilocos Norte"
}

City Serializer

Generate region serializer with rails g serializer city.

 root@0122:/usr/src/app# rails g serializer city
      create  app/serializers/city_serializer.rb                                                           

This will create a file named city_serializer.rb under the app/serializers directory. Move to the file and introduce the attributes you want to be include in serialization. Suppose we just want to add name, province and id attributes of project while serializing.

Now we create a serializer called CitySerializer.

# app/serializer/city_serializer.rb

class CitySerializer < ActiveModel::Serializer
  attributes :id, :province, :name

  def province
    object.province.name
  end
end

In the app/controllers/api/v1, after we collect the attributes in CitySerializer, add the CitySerializer to our cities_controller.rb like this:

# app/controllers/api/v1/cities_controller.rb

class Api::V1::CitiesController < ApplicationController

  def index
    province = Address::Province.find_by_id(params[:province_id])
    cities = if province
               province.cities
             else
               Address::City.all
             end

-    render json: cities
+    render json: cities, each_serializer: CitySerializer
  end

  def show
    city = Address::City.find(params[:id])
-   render json: city
+   render json: city, serializer: CitySerializer
  end
end

This is the differences of with and without serializer

Without Serializer

http://localhost:3000/api/v1/provinces/10/cities

[
    {
      "id": 219,
      "province_id": 10,
      "code": "030801000",
      "name": "Abucay",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 220,
      "province_id": 10,
      "code": "030802000",
      "name": "Bagac",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    # ...
]

http://localhost:3000/api/v1/cities/

[
    {
      "id": 1,
      "province_id": 1,
      "code": "012801000",
      "name": "Adams",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2,
      "province_id": 1,
      "code": "012802000",
      "name": "Bacarra",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    # ...
]

http://localhost:3000/api/v1/cities/100

{
    "id": 100,
    "province_id": 4,
    "code": "015523000",
    "name": "Mabini",
    "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
    "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
}

With Serializer

http://localhost:3000/api/v1/provinces/10/cities

[
    {
      "id": 219,
      "province": "Bataan",
      "name": "Abucay"
    },
    {
      "id": 220,
      "province": "Bataan",
      "name": "Bagac"
    },
    # ...
]

http://localhost:3000/api/v1/cities/

[
    {
      "id": 1,
      "province": "Ilocos Norte",
      "name": "Adams"
    },
    {
      "id": 2,
      "province": "Ilocos Norte",
      "name": "Bacarra"
    },
    # ...
]

http://localhost:3000/api/v1/cities/100

    {
      "id": 100,
      "province": "Pangasinan",
      "name": "Mabini",
    }

Barangay Serializer

Generate barangay serializer with rails g serializer barangay.

 root@0122:/usr/src/app# rails g serializer barangay
      create  app/serializers/barangay_serializer.rb                                                           

This will create a file named barangay_serializer.rb under the app/serializers directory. Move to the file and introduce the attributes you want to be include in serialization. Suppose we just want to add name, city and id attributes of project while serializing.

Now we create a serializer called BarangaySerializer.

# app/serializer/barangay_serializer.rb

class BarangaySerializer < ActiveModel::Serializer
  attributes :id, :city, :name

  def city
    object.city.name
  end
end

In the app/controllers/api/v1, after we collect the attributes in BarangaySerializer, add the BarangaySerializer to our barangays_controller.rb like this:

# app/controllers/api/v1/barangays_controller.rb

class Api::V1::BarangaysController < ApplicationController

  def index
    city = Address::City.find_by_id(params[:city_id])
    barangays = if city
                  city.barangays
                else
                  Address::Barangay.all
                end
-   render json: barangays
+   render json: barangays, each_serializer: BarangaySerializer
  end

  def show
    barangay = Address::Barangay.find(params[:id])
-   render json: barangay
+   render json: barangay, serializer: BarangaySerializer
  end
end

This is the differences of with and without serializer

Without Serializer

http://localhost:3000/api/v1/cities/100/barangays

[
    {
      "id": 2444,
      "city_id": 100,
      "code": "015523002",
      "name": "Bacnit",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2445,
      "city_id": 100,
      "code": "015523003",
      "name": "Barlo",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    # ...
]

http://localhost:3000/api/v1/barangays

[
    {
      "id": 1,
      "city_id": 1,
      "code": "012801001",
      "name": "Adams (Pob.)",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
    {
      "id": 2,
      "city_id": 2,
      "code": "012802001",
      "name": "Bani",
      "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
      "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
    },
]

http://localhost:3000/api/v1/barangays/86

{
    "id": 86,
    "city_id": 4,
    "code": "012804011",
    "name": "Payac",
    "created_at": "XXXX-XX-XXTXX:XX:XX.XXXZ",
    "updated_at": "XXXX-XX-XXTXX:XX:XX.XXXZ"
}

With Serializer

http://localhost:3000/api/v1/cities/100/barangays

[
    {
      "id": 2444,
      "city": "Mabini",
      "name": "Bacnit"
    },
    {
      "id": 2445,
      "city": "Mabini",
      "name": "Barlo"
    # ...
]

http://localhost:3000/api/v1/barangays

[
    {
      "id": 1,
      "city": "Adams",
      "name": "Adams (Pob.)"
    },
    {
      "id": 2,
      "city": "Bacarra",
      "name": "Bani"
    },
    # ...
]

http://localhost:3000/api/v1/barangays/86

{
    "id": 86,
    "city": "Bangui",
    "name": "Payac"
}

Now we successfully integrate serializer into our application. You can check Serializer for more details.


Back to top

Copyright © 2020-2022 Secure Smarter Service, Inc. This site is powered by KodaCamp.