module SoberSwag module Reporting module Output ## # Augment outputs with the ability to select views. # This models a 'oneOf' relationship, where the choice picked is controlled by the 'view' parameter. # # This is "optional choice," in the sense that you *must* provide a default `:base` key. # This key will be used in almost all cases. class Viewed < Base ## # @param views [Hash<Symbol,Interface>] a map of view key to view. # Note: this map *must* include the base view. def initialize(views) @view_map = views raise ArgumentError, 'views must have a base key' unless views.key?(:base) end attr_reader :view_map ## # Serialize out an object. # If the view key is not provided, use the base view. # # @param input [Object] object to serialize # @param view [Symbol] which view to use. # If view is not valid, an exception will be thrown # @raise [KeyError] if view is not valid # @return [Object,String,Array,Numeric] JSON-serializable object. # Suitable for use with #to_json. def call(input, view: :base) view(view).call(input) end def serialize_report(input) view(:base).call(input) end ## # Get a view with a particular key. def view(view) view_map.fetch(view) end ## # @return [Set<Symbol>] all of the views applicable. def views view_map.keys.to_set end ## # Add (or override) the possible views. # # @return [Viewed] a new view map, with one more view. def with_view(name, val) Viewed.new(views.merge(name => val)) end def swagger_schema found = {} possibles = view_map.values.flat_map do |v| view_item, view_found = v.swagger_schema found.merge!(view_found) view_item[:oneOf] || [view_item] end [{ oneOf: possibles }, found] end end end end end