Skip to content

[RFC] Automatic serializer lookup #1442

Open
@beauby

Description

@beauby

TL;DR

What should be the lookup mechanism when inferring a serializer for a resource?

Proposal

What seems to make most sense is the following:

# resource.class == ::ResNamespace::Resource
# controller.class == ::Api::V1::ResourcesController
lookup_chain = prefixes(controller.class.to_s).map { |p| "#{p}::#{resource.class}Serializer" }
# => [ "::Api::V1::ResourcesController::ResNamespace::ResourceSerializer", 
# "::Api::V1::ResNamespace::ResourceSerializer",
# "::Api::ResNamespace::ResourceSerializer",
# "::ResNamespace::ResourceSerializer" ]

# When the resource is serialized as an association of an other serializer, say SerNamespace::OtherResourceSerializer,
# add "SerNamespace::OtherResourceSerializer::ResNamespace::ResourceSerializer" at the beginning of the lookup chain 

Implemented in #1436.

Current situation

Work has been done to get us to a more flexible situation in this regard.

The whole automatic lookup can be disabled by setting ActiveModelSerializers.config.automatic_lookup = false from within an initializer.

Currently, for a resource CoolNamespace::CoolResource, AMS will look for a CoolResourceSerializer in the following namespaces:

  • If it is being serialized as an association of some other resource using OtherNamespace::OtherResourceSerializer, first look for OtherNamespace::OtherResourceSerializer::CoolResourceSerializer (this is designed so that defining single-purpose serializers for associations is less cumbersome),
  • otherwise, look for CoolNamespace::CoolResourceSerializer (this is kind of the "normal" lookup),
  • if none is found, recursively do the same for the superclass of CoolResource.

Other possible places we might want to look at:

  • the calling controller's namespace (Controller namespace lookup. #1436), i.e. when doing render json: @posts inside Api::V1::PostsController#index, look for Api::V1::PostSerializer,
  • the calling controller's namespace, concatenated with the resource's namespace, i.e. when doing render json: @cool_resources inside Api::V1::CoolResourcesController#index, look for Api::V1::CoolNamespace::CoolResourceSerializer (@natematykiewicz),
  • all of the calling controller's prefix namespaces (in the previous case it would be ::Api::V1, ::Api, and ::,
  • the parent serializer's namespace, i.e. when serializing CoolResource as an association through OtherNamespace::OtherResourceSerializer, look for OtherNamespace::CoolResourceSerializer (so that when you do render @post, serializer: Experimental::CoolFeature::PostSerializer, the post's author can be inferred to be Experimental::CoolFeature::AuthorSerializer),
  • a user-specified list of namespaces,
  • possibly many other things.

Possible API for user-provided paths

  • add callbacks at the beginning and end of the lookup chain

Please chip in with your ideas, use-cases and strong opinions!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions