Skip to content

Instantly share code, notes, and snippets.

@NaumenkoSergiy
Last active July 21, 2023 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NaumenkoSergiy/5b0bc489ee5202207e1f4bc386030673 to your computer and use it in GitHub Desktop.
Save NaumenkoSergiy/5b0bc489ee5202207e1f4bc386030673 to your computer and use it in GitHub Desktop.
Alba and Panko serializers

Panko:

  • ability to “include” serializer relationship from controllers
  • pass params or context from controllers to serializer objects
  • for relationships (has_one/many/belongs_to) in serializer
  • conditionally include attributes/relationships in serializer (if:)
  • overwrite attributes in serializer
  • only return specific fields (fields:)
  • ability to define non-active-record response serializers

Alba:

  • ability to “include” serializer relationship from controllers
  • pass params or context from controllers to serializer objects
  • for relationships (has_one/many/belongs_to) in serializer
  • conditionally include attributes/relationships in serializer (if:)
  • overwrite attributes in serializer
  • only return specific fields (fields:)
  • ability to define non-active-record response serializers

Based on these criteria we can use Alba serializer, and I think missing functionality for "ability to “include” serializer relationship from controllers" is not a bit deal, because we can use parameters to define what relationships need to add.

Example of using AgreementSerializer with Alba:

  class BaseSerializer
    include Alba::Resource

    root_key :data

    def initialize(data, options = {})
      super(data)

      @data = data
      @meta_data = options[:meta_data] || {}
      @params = options[:params] || {}
      @fields = options[:fields] || {}
    end

    meta do
      @meta_data
    end

    def serialize
      super(root_key: :data)
    end
  end
end

module App
  class AgreementSerializer < BaseSerializer
    attributes :id, :title, :slug, :source
    attribute :source, &:source_enum
  
    has_many :agreement_contacts, if: proc { @params[:full_profile] }
  end
end


=> App::AgreementSerializer.new(Agreement.limit(5).includes(:contacts), params: {full_profile: true}, meta_data: {total_count: 20}).serialize

Result:

{"data"=>
  [{"id"=>5,
    "title"=>"Test12",
    "slug"=>"a0782ce98359",
    "source"=>"email",
    "agreement_contacts"=>
     [{"id"=>74,
       "contact"=>
        {"id"=>20,
         "full_name"=>"dsds dscs",
         "user_id"=>nil,
         "slug"=>"bf1841fd875d",
         "email"=>nil,
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}}]},
   {"id"=>14,
    "title"=>"TEST A",
    "slug"=>"7f989ab3ae15",
    "source"=>"app",
    "agreement_contacts"=>
     [{"id"=>81,
       "contact"=>
        {"id"=>5,
         "full_name"=>"Serhii Testrfrvrgvfrvrrvr",
         "user_id"=>nil,
         "slug"=>"81b30087d9a3",
         "email"=>"sergey.naumenko94+2@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}},
      {"id"=>82,
       "contact"=>
        {"id"=>6,
         "full_name"=>"Serhii Test",
         "user_id"=>nil,
         "slug"=>"bb90d5833fe6",
         "email"=>"sergey.naumenko94+3@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}},
      {"id"=>83,
       "contact"=>
        {"id"=>28,
         "full_name"=>"dfcedfe fcedfe",
         "user_id"=>nil,
         "slug"=>"04a33050c801",
         "email"=>nil,
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}}]},
   {"id"=>12,
    "title"=>"test",
    "slug"=>"0bef7bc058da",
    "source"=>"app",
    "agreement_contacts"=>
     [{"id"=>79,
       "contact"=>
        {"id"=>7,
         "full_name"=>"Serhii1 Naumenko",
         "user_id"=>nil,
         "slug"=>"651ca01add21",
         "email"=>"sergey.naumenko94+4@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}}]},
   {"id"=>15,
    "title"=>"Naumenko",
    "slug"=>"81dd104bbf82",
    "source"=>"app",
    "agreement_contacts"=>
     [{"id"=>84,
       "contact"=>
        {"id"=>5,
         "full_name"=>"Serhii Testrfrvrgvfrvrrvr",
         "user_id"=>nil,
         "slug"=>"81b30087d9a3",
         "email"=>"sergey.naumenko94+2@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}},
      {"id"=>85,
       "contact"=>
        {"id"=>7,
         "full_name"=>"Serhii1 Naumenko",
         "user_id"=>nil,
         "slug"=>"651ca01add21",
         "email"=>"sergey.naumenko94+4@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}}]},
   {"id"=>17,
    "title"=>"testtt",
    "slug"=>"53ce62125a04",
    "source"=>"app",
    "agreement_contacts"=>
     [{"id"=>87,
       "contact"=>
        {"id"=>5,
         "full_name"=>"Serhii Testrfrvrgvfrvrrvr",
         "user_id"=>nil,
         "slug"=>"81b30087d9a3",
         "email"=>"sergey.naumenko94+2@gmail.com",
         "department_id"=>2,
         "disclosure_search_count"=>nil,
         "position_title"=>nil,
         "location"=>nil,
         "phone_number"=>nil,
         "organization_id"=>22606,
         "disclosure_forward_citation_count"=>nil}}]}],
 "meta"=>{"total_count"=>20}}

Non ActiveRecord Serializer:

module App
  module Response
    class SearchSerializer < BaseSerializer
      include Alba::Resource

      attributes :patent_count_by_year_by_classifications

      def initialize(data)
        super(data)
        @data = data
      end

      def patent_count_by_year_by_classifications
        @data[:patent_count_by_year_by_classifications] || []
      end
    end
  end
end

----------------------------------------------------------

Foo = Struct.new(:patent_count_by_year_by_classifications)
foo = Foo.new([])
App::Response::SearchSerializer.new(foo).serialize

=> {"data"=>{"patent_count_by_year_by_classifications"=>[]}, "meta"=>{}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment