ApplicationSerializer provides contextual serialization for ActiveModels. It preserves the original interface of ActiveModelSerializers, allowing flexibility with existing Serializers without polluting controllers with Adapter settings.
- active_model_serializers (>= 0.10.12)
Add this line to your application's Gemfile:
gem'application_serializer'And then execute:
$ bundle
ApplicationSerializer is intended for existing Rails APIs that need contextual rendering of models. The goal is to centralize changes to the Serializers.
Autoload your Serializers directory.
# config/application.rbmoduleApiDemoclassApplication < Rails::Application# omittedconfig.autoload_paths << Rails.root.join('serializers')endendThe scope passed to the Serializer (accessible by the scope argument in the block) is defined in your controllers. This can be any object or value returned by the serialization_scope helper.
This helper function must return a scope as a hash with the key context or an object that responds to a context method. The context attribute/method will trigger the appropriate context block defined in your Serializer. If the context is not defined, it defaults to the default context.
# app/controllers/people_controller.rbclassPersonController < ApplicationControllerserialization_scope:serialization_context### this will trigger the context :index block if the ?context parameter is not present# to trigger the context :list block, make a network call containing ?context=list##defindex# logic omitted for brevityrenderjson: Person.allend# this will trigger the context :default blockdefshow# logic omitted for brevityrenderjson: Person.where(id: params[:id])endprivate### allow a ?context=value flag, fall back on the controller action##defserialization_context{context: (params[:context] || params[:action]).to_sym,user: current_user}endendAn existing Serializer for a "Person" model would be defined like so:
# app/serializers/person_serializer.rbclassPersonSerializer < ActiveModel::Serializerattributes:id,:name,:catch_phraseendUsing ApplicationSerializer, your new Serializer can inherit from ApplicationSerializer::Base without impacting any of the existing functionality.
# app/serializers/person_serializer.rbclassPersonSerializer < ApplicationSerializer::Baseattributes:id,:name,:catch_phraseendAs defined, all contexts will include the id, name, and catch_phrase attributes of the model you're serializing regardless of context. If you want to limit attributes based on scope, you must use the context block.
The context block accepts a context name symbol and a block with 3 arguments: the serializer (to set attributes), the scope, and the model being serialized. See ActiveModelSerializers for implementation details.
# app/serializers/person_serializer.rbclassPersonSerializer < ApplicationSerializer::Basecontext:defaultdo |serialize|
serialize.attributes:name,:catch_phraseendcontext:indexdo |serialize|
serialize.attributes:nameend# Example:# return a hash containing a key => object.id, value => object.name to populate a select listcontext:listdo |serialize,scope|
serialize.attribute:id,key: :keyserialize.attribute:name,key: :valueendendEach serializer has a class-level attribute descriptor cache for each of the contexts you define. These are cached at run-time.
The cache for each serializer can be cleared by calling YourSerializer.context_cache.clear!
Serializers serving different contexts should always have supporting unit tests. The context and scope parameters are passed through the constructor of the serializer.
require'minitest/autorun'classTestPersonSerializer < MiniTest::Unit::TestCasedefsetup@model_attributes={id: 1,name: 'Bender',catch_phrase: 'Bender is great'}@person=Person.new(@model_attributes)enddeftest_default_contextjson_string=PersonSerializer.new(@person,scope: {context: :default}).to_jsonassert_equal({id: @model_attributes[:id]}.to_json),json_stringenddeftest_list_contextjson_string=PersonSerializer.new(@person,scope: {context: :list}).to_jsonassert_equal({value: @model_attributes[:id],key: @model_attributes[:name]}.to_json),json_stringendendBug reports and pull requests are welcome on GitHub at https://github.com/Vandise/application_serializer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the ApplicationSerializer project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.