class TinySerializer

Simple DSL for converting objects to Hashes, which is mostly API-compatible with ActiveModel::Serializer. The Hashes can be rendered as JSON by Rails.

I have also added some fast_jsonapi API parameters that do nothing, to ease later transition to that library.

Usage

# my_object.rb
MyObject = Struct.new(:id, :first_name, :last_name, :date) do
  def parent; nil; end
  def sub_record; nil; end
  def related_items; []; end
end

# my_object_serializer.rb
class MyObjectSerializer < TinySerializer
  attributes :id,
             :first_name,
             :last_name,
             :date

  belongs_to :parent, serializer: ParentSerializer
  has_one :sub_record # serializer will be inferred to be SubRecordSerializer
  has_many :related_items, serializer: RelatedItemSerializer

  attribute :full_name do
    "#{object.first_name} #{object.last_name}"
  end
end

# my_objects_controller.rb
def show
  @my_object = MyObject.new(1, "Fred", "Flintstone", Date.new(2000, 1, 1))
  render json: MyObjectSerializer.new(@my_object).serialize
end

RailsExtensions

The RailsExtensions module is automatically prepended when TinySerializer is used in a Rails app. It defines some small convenience instance methods.

Constants

VERSION

Attributes

logger[RW]

Optional logger object. Defaults to Rails.logger in a Rails app.

object[RW]

The object to serialize as a Hash

options[RW]

Hash of data to be passed to blocks

Public Class Methods

is_collection?(object) click to toggle source

Check if object is a collection.

# File lib/tiny_serializer.rb, line 136
def is_collection?(object)
  object.respond_to?(:each) && !object.respond_to?(:each_pair)
end
new(object, options = {}) click to toggle source

Create a new serializer instance.

object

The object to serialize. Can be a single object or a collection of objects.

# File lib/tiny_serializer.rb, line 76
def initialize(object, options = {})
  @object = object
  @options = options
end
serialize(object, options = {}) click to toggle source

The same as:

TinySerializer.new(object).serializable_hash
# File lib/tiny_serializer.rb, line 124
def serialize(object, options = {})
  new(object, options).serializable_hash
end
serialize_each(collection) click to toggle source

Same as serialize, but raises ArgumentError if `collection` doesn't appear to be a collection.

# File lib/tiny_serializer.rb, line 130
def serialize_each(collection)
  raise ArgumentError, "collection does not appear to be a collection" unless is_collection?(collection)
  new(collection).serializable_hash
end

Public Instance Methods

as_json(_ = nil) click to toggle source

Serialize object as a Hash, then call as_json on the Hash, which will convert keys to Strings.

There shouldn't be a need to call this, but we implement it to fully support ActiveSupport's magic JSON protocols.

# File lib/tiny_serializer.rb, line 101
def as_json(_ = nil)
  serializable_hash.as_json
end
collection?() click to toggle source

Return true if object is a collection.

# File lib/tiny_serializer.rb, line 115
def collection?
  self.class.is_collection?(@object)
end
serializable_hash(_ = nil) click to toggle source

Serialize object as a Hash with Symbol keys. Returns nil if object is nil.

# File lib/tiny_serializer.rb, line 83
def serializable_hash(_ = nil)
  return serialize_single_object_to_hash unless collection?

  json = []
  @object.each do |object|
    json << self.class.new(object, @options).serializable_hash
  end
  json
end
Also aliased as: to_hash, serialize
serialize(_ = nil)
Alias for: serializable_hash
to_hash(_ = nil)
Alias for: serializable_hash
to_json(_ = nil) click to toggle source

Serialize object to a JSON String.

Calls serializable_hash, then call to_json on the resulting Hash, converting it to a String using the automatic facilities for doing so from ActiveSupport.

# File lib/tiny_serializer.rb, line 110
def to_json(_ = nil)
  serializable_hash.to_json
end

Private Instance Methods

get_attribute(name, block) click to toggle source
# File lib/tiny_serializer.rb, line 162
def get_attribute(name, block)
  if block
    instance_exec(@object, @options, &block)
  else
    @object.public_send(name)
  end
end
get_collection(name, block) click to toggle source

Get the collection from object or block, or [] if nil.

# File lib/tiny_serializer.rb, line 206
def get_collection(name, block)
  if block
    instance_exec(@object, @options, &block)
  else
    @object.public_send(name)
  end || []
end
serialize_attribute(raw_value, is_id = false) click to toggle source

Internal algorithm to convert any object to a valid JSON string, scalar, object, array, etc. All objects are passed through this function after they are retrieved from object. Currently just calls as_json.

# File lib/tiny_serializer.rb, line 173
def serialize_attribute(raw_value, is_id = false)
  if is_id && coerce_ids_to_string?
    serialize_id(raw_value)
  else
    raw_value.as_json
  end
end
serialize_attributes(hash) click to toggle source
# File lib/tiny_serializer.rb, line 155
def serialize_attributes(hash)
  self.class.attributes.each do |name, key, is_id, block|
    raw_value = get_attribute(name, block)
    hash[key] = serialize_attribute(raw_value, is_id)
  end
end
serialize_collections(hash) click to toggle source
# File lib/tiny_serializer.rb, line 192
def serialize_collections(hash)
  self.class.collections.each do |collection_name, key, serializer, block|
    collection = get_collection(collection_name, block)

    json_array = []
    collection.each do |object|
      json_array << serializer.new(object, @options).serializable_hash
    end

    hash[key] = json_array
  end
end
serialize_id(id) click to toggle source
# File lib/tiny_serializer.rb, line 181
def serialize_id(id)
  id && id.to_s
end
serialize_single_object_to_hash() click to toggle source

Private serialization implementation for a single object. @object must be a single object.

# File lib/tiny_serializer.rb, line 145
def serialize_single_object_to_hash
  return nil if @object.nil?

  hash = {}
  serialize_attributes(hash)
  serialize_sub_records(hash)
  serialize_collections(hash)
  hash
end
serialize_sub_records(hash) click to toggle source
# File lib/tiny_serializer.rb, line 185
def serialize_sub_records(hash)
  self.class.sub_records.each do |name, key, serializer, block|
    record = get_attribute(name, block)
    hash[key] = serializer.new(record, @options).serializable_hash
  end
end