Skip to content

LaunchPadLab/lp-serializable

Repository files navigation

Lp::Serializable

When serializing with fast_jsonapi, data is structured per the json-api specs.

lp-serializable is a thin wrapper around fast_jsonapi serialization, producting AMS style output.

lp-serializable is intended to be used in Rails controllers.

Installation

Add this line to your application's Gemfile:

gem 'lp-serializable'

And then execute:

$ bundle

Or install it yourself as:

$ gem install lp-serializable

Usage

Controller Definition

class ApplicationController < ActionController::Base
  include Lp::Serializable
end

class MoviesController < ApplicationController
  def index
    movies = Movie.all
    movies_hash = serializable_collection(movies, 'Movie')
    render json: movies_hash
  end

  def show
    movie = Movie.find(params[:id])
    movie_hash = serializable(movie)
    render json: movie_hash
  end
end

Serializer Definition

class MovieSerializer
  include FastJsonapi::ObjectSerializer

  attributes :name
  
  attribute :year, if: Proc.new { |object| object.year.present? }
  
  attribute :last_updated do |object|
    object.updated_at
  end

  has_many :actors
  belongs_to :owner
end

class ActorSerializer
  include FastJsonapi::ObjectSerializer
    
  attributes :id
end

class OwnerSerializer
  include FastJsonapi::ObjectSerializer

  attributes :id
end

Object Serialization

Sample Object

movie = Movie.new
movie.id = 232
movie.name = 'test movie'
movie.actor_ids = [1, 2, 3]
movie.owner_id = 3
movie.movie_type_id = 1
movie

Return a hash

hash = serializable(movie)

Output

{
  "data": {
    "id": "3",
    "type": "movie",
    "name": "test movie",
    "last_updated": "2019-04-26 18:55:46 UTC",
    "actors": [
        {
            "id": "1",
            "type": "actor"
        },
        {
            "id": "2",
            "type": "actor"
        }
    ],
    "owner": {
        "id": "3",
        "type": "user"
    }
  }
}

For more information on configuration, refer to fast_jsonapi documentation.

Deeply Nested Serialization Pattern

Fastjson API does not support serialization of deeply nested resources.

To get around this, extend Lp::Serializable in your serializers:

class MovieSerializer
  include FastJsonapi::ObjectSerializer
  extend Lp::Serializable

 ...
end

Define custom attributes for relationships, instead of defining them via fastjson_api:

class MovieSerializer
  include FastJsonapi::ObjectSerializer
  extend Lp::Serializable

 attribute :actors do |object|
  collection = object.actors
  serializer = 'Actor'
  serializable_collection(collection, serializer, nested: true)
 end
end

Attribute :actors will trigger ActorSerializer to serialize the actors collection. Consequently, any relationships defined in ActorSerializer via custom attributes and serialized with serializable_ methods (using the nested: true option) will be appropriately nested.

Custom Serializer Class

Use #serializable_class to serialize with a custom class:

  def show
    movie = Movie.find(params[:id])
    # Will serialize with FilmSerializer instead of MovieSerializer
    movie_hash = serializable_class(movie, 'Film')
    render json: movie_hash
  end

Options Support

Supported options include:

Other options are "supported" but may yeild unexpected results, as Serializable's hash flattening prioritizes deeply nested data structures.

:is_collection is baked into Seriazable methods for accurate detection of collections or singular resources.

Aliases

  • serialize_and_flatten() = serializable()
  • serialize_and_flatten_with_class_name() = serializable_class()
  • serialize_and_flatten_collection() = serializable_collection()

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/LaunchPadLab/lp-serializable. 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 Lp::Serializable project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.