class SoberSwag::OutputObject

Create a serializer that is heavily inspired by the “Blueprinter” library. This allows you to make “views” and such inside.

Under the hood, this is actually all based on {SoberSwag::Serializer::Base}.

Attributes

fields[R]

@return [Array<SoberSwag::OutputObject::Field>]

identifier[R]

@return [String] the external ID to use for this object

views[R]

@return [Array<SoberSwag::OutputObject::View>]

Public Class Methods

define(&block) click to toggle source

Use a OutputObject to define a new serializer. It will be based on {SoberSwag::Serializer::Base}.

An example is illustrative:

PersonSerializer = SoberSwag::OutputObject.define do
  field :id, primitive(:Integer)
  field :name, primitive(:String).optional

  view :complex do
    field :age, primitive(:Integer)
    field :title, primitive(:String)
  end
end

Note: This currently will generate a new class that does serialization. However, this is only a hack to get rid of the weird naming issue when generating swagger from dry structs: their section of the schema area is defined by their *Ruby Class Name*. In the future, if we get rid of this, we might be able to keep this on the value-level, in which case {.define} can simply return an instance of SoberSwag::Serializer that does the correct thing, with the name you give it. This works for now, though.

@return [Class] the serializer generated. @yieldself [SoberSwag::OutputObject::Definition]

# File lib/sober_swag/output_object.rb, line 41
def self.define(&block)
  d = Definition.new.tap do |o|
    o.instance_eval(&block)
  end
  new(d.fields, d.views, d.identifier)
end
new(fields, views, identifier) click to toggle source

@param fields [Array<SoberSwag::OutputObject::Field>] the fields for this OutputObject @param views [Array<SoberSwag::OutputObject::View>] the views for this OutputObject @param identifier [String] the external identifier for this OutputObject

# File lib/sober_swag/output_object.rb, line 52
def initialize(fields, views, identifier)
  @fields = fields
  @views = views
  @identifier = identifier
end

Public Instance Methods

base() click to toggle source

A serializer for the “base type” of this OutputObject, with no views.

# File lib/sober_swag/output_object.rb, line 93
def base
  base_serializer
end
base_serializer() click to toggle source

@return [SoberSwag::Serializer::FieldList] serializer for this output object.

# File lib/sober_swag/output_object.rb, line 120
def base_serializer
  @base_serializer ||= SoberSwag::Serializer::FieldList.new(fields).tap do |s|
    s.identifier(identifier)
  end
end
serialize(obj, opts = {}) click to toggle source

Perform serialization.

# File lib/sober_swag/output_object.rb, line 70
def serialize(obj, opts = {})
  serializer.serialize(obj, opts)
end
serializer() click to toggle source

Compile down this to an appropriate serializer. It uses {SoberSwag::Serializer::Conditional} to do view-parsing, and {SoberSwag::Serializer::FieldList} to do the actual serialization.

@todo: optimize view selection to use binary instead of linear search

# File lib/sober_swag/output_object.rb, line 103
def serializer
  @serializer ||=
    begin
      view_choices = views.map { |view| [view.name.to_s, view.serializer] }.to_h
      view_choices['base'] = base_serializer
      SoberSwag::Serializer::Hash.new(view_choices, base, proc { |_, options| options[:view]&.to_s })
    end
end
to_s() click to toggle source

@return [String]

# File lib/sober_swag/output_object.rb, line 114
def to_s
  "<SoberSwag::OutputObject(#{identifier})>"
end
type() click to toggle source

Get a Dry::Struct of the type this OutputObject will serialize to.

# File lib/sober_swag/output_object.rb, line 76
def type
  serializer.type
end
view(name) click to toggle source

Get a serializer for a single view contained in this output object. Note: given `:base`, it will return a serializer for the base OutputObject @param name [Symbol] the name of the view @return [SoberSwag::Serializer::Base] the serializer

# File lib/sober_swag/output_object.rb, line 85
def view(name)
  return base_serializer if name == :base

  @views.find { |v| v.name == name }
end