Skip to content

Repository files navigation

ApplicationSerializer

Application Serializer Test Suite

ApplicationSerializer provides contextual serialization for ActiveModels. It preserves the original interface of ActiveModelSerializers, allowing flexibility with existing Serializers without polluting controllers with Adapter settings.

Requirements

  • active_model_serializers (>= 0.10.12)

Installation

Add this line to your application's Gemfile:

gem'application_serializer'

And then execute:

$ bundle

Usage

ApplicationSerializer is intended for existing Rails APIs that need contextual rendering of models. The goal is to centralize changes to the Serializers.

Rails Configuration

Autoload your Serializers directory.

# config/application.rbmoduleApiDemoclassApplication < Rails::Application# omittedconfig.autoload_paths << Rails.root.join('serializers')endend

Defining the Context and Scope

The 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}endend

Update Your Serializers

An existing Serializer for a "Person" model would be defined like so:

# app/serializers/person_serializer.rbclassPersonSerializer < ActiveModel::Serializerattributes:id,:name,:catch_phraseend

Using 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_phraseend

As 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.

context(name<symbol> &block<serializer, user_defined_scope, model>)

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: :valueendend

Caching

Each 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!

Testing

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_stringendend

Contributing

Bug 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.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the ApplicationSerializer project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

About

Contextual Serialization for ActiveModel applications

Resources

Code of conduct

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages