Class: SoberSwag::Reporting::Input::Struct

Inherits:
Object
  • Object
show all
Extended by:
Interface
Includes:
Comparable
Defined in:
lib/sober_swag/reporting/input/struct.rb

Overview

Base class of input structs.

These allow you to define both an input type and a ruby type at once. They provide a fluid interface for doing so.

Classes which inherit from Struct "quack like" an Interface, so you can use them as input type definitions.

You should add attributes using the Struct.attribute or Struct.attribute? methods. These also let you nest definitions, so this is okay:

class Person < SoberSwag::Reporting::Input::Struct
  attribute :first_name, SoberSwag::Reporting::Input.text
  attribute :stats do
    attribute :average_score, SoberSwag::Reporting::Input.number
  end
end

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Interface

add_schema_key, call!, described, enum, format, in_range, list, mapped, modify_schema, multiple_of, optional, or, referenced, swagger_path_schema, swagger_query_schema, |

Constructor Details

#initialize(props) ⇒ Struct

Returns a new instance of Struct.



205
206
207
# File 'lib/sober_swag/reporting/input/struct.rb', line 205

def initialize(props)
  @struct_properties = props
end

Class Attribute Details

.parent_structSoberSwag::Reporting::Input::Struct?

Returns the struct we inherit from. Used to implement allOf style inheritance.

Returns:



103
104
105
# File 'lib/sober_swag/reporting/input/struct.rb', line 103

def parent_struct
  @parent_struct
end

Instance Attribute Details

#struct_propertiesObject (readonly)

Returns the value of attribute struct_properties.



209
210
211
# File 'lib/sober_swag/reporting/input/struct.rb', line 209

def struct_properties
  @struct_properties
end

Class Method Details

.add_attribute!(name, input, required:, description: nil) ⇒ Object

Add an attribute, specifying if it is required or not via an argument. You should use #attribute or #attribute? instead of this almost always.

Parameters:

  • name (Symbol)

    name of this attribute

  • input (Interface)

    type fot this attribue

  • required (true, false)

    if this attribute is required

  • description (String, nil) (defaults to: nil)

    optional description for this attribute

Raises:

  • (ArgumentError)


77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sober_swag/reporting/input/struct.rb', line 77

def add_attribute!(name, input, required:, description: nil)
  raise ArgumentError, 'name must be a symbol' unless name.is_a?(Symbol)
  raise ArgumentError, "input type must be a SoberSwag::Reporting::Input::Interface (at key #{name.inspect})" unless input.is_a?(Interface)

  define_attribute(name) # defines an instance method to access this attribute

  object_properties[name] = Object::Property.new(
    input,
    required: required,
    description: description
  )
end

.attribute(name, input, description: nil) ⇒ Object .attribute(name, description: nil, &block) ⇒ Object

Overloads:

  • .attribute(name, input, description: nil) ⇒ Object

    Define a new attribute, which will be required.

    Parameters:

    • name (Symbol)

      the name of this attribute

    • input (Interface)

      input reporting type

    • description (String, nil) (defaults to: nil)

      description for this attribute

  • .attribute(name, description: nil, &block) ⇒ Object

    Define a new nested attribute, which will be required, using a block to describe a sub-struct. This block will immediately be evaluated to create a child struct.

    Parameters:

    • name (Symbol)

      the name of the attribute. The sub-struct defined will be stored in a constant on this class, under this name, classified.

      So if the name is :first_name, then the constant will be FirstName

    • description (String, nil) (defaults to: nil)

      describe this attribute



41
42
43
44
# File 'lib/sober_swag/reporting/input/struct.rb', line 41

def attribute(name, input = nil, description: nil, &block)
  input_type = make_input_type(name, input, block)
  add_attribute!(name, input_type, required: true, description: description)
end

.attribute?(name, input, description: nil) ⇒ Boolean .attribute?(name, description: nil, &block) ⇒ Boolean

Overloads:

  • .attribute?(name, input, description: nil) ⇒ Boolean

    Define a new attribute, which will be not required.

    Parameters:

    • name (Symbol)

      the name of this attribute

    • input (Interface)

      input reporting type

    • description (String, nil) (defaults to: nil)

      description for this attribute

  • .attribute?(name, description: nil, &block) ⇒ Boolean

    Define a new nested attribute, which will not be required, using a block to describe a sub-struct. This block will immediately be evaluated to create a child struct.

    Parameters:

    • name (Symbol)

      the name of the attribute. The sub-struct defined will be stored in a constant on this class, under this name, classified.

      So if the name is :first_name, then the constant will be FirstName

    • description (String, nil) (defaults to: nil)

      describe this attribute

Returns:

  • (Boolean)


62
63
64
65
66
# File 'lib/sober_swag/reporting/input/struct.rb', line 62

def attribute?(name, input = nil, description: nil, &block)
  input_type = make_input_type(name, input, block)

  add_attribute!(name, input_type, required: false, description: description)
end

.call(attrs) ⇒ SoberSwag::Reporting::Input::Struct, SoberSwag::Reporting::Report::Base

Returns the struct class, or a report of what went wrong.

Returns:



139
140
141
# File 'lib/sober_swag/reporting/input/struct.rb', line 139

def call(attrs)
  input_type.call(attrs)
end

.define_attribute(name) ⇒ Object (private)

Quick method which defines an accessor method for this struct.



187
188
189
190
191
192
193
194
# File 'lib/sober_swag/reporting/input/struct.rb', line 187

def define_attribute(name)
  define_method(name) do
    struct_properties[name]
  end
  define_method("#{name}_present?") do
    struct_properties.key?(name)
  end
end

.identifierString? .identifier(val) ⇒ String

Overloads:

  • .identifierString?

    Returns the identifier for this object, used for its reference path.

    Returns:

    • (String, nil)

      the identifier for this object, used for its reference path.

  • .identifier(val) ⇒ String

    Sets an identifier for this struct.

    Parameters:

    • val (String)

      the identifier to set

    Returns:

    • (String)

      the set identifier.



128
129
130
131
132
133
134
# File 'lib/sober_swag/reporting/input/struct.rb', line 128

def identifier(val = nil)
  if val
    @identifier = val
  else
    @identifier || name&.gsub('::', '.')
  end
end

.inherited(other) ⇒ Object

Used to implement allOf style inheritance by setting #parent_struct on the object that is inheriting from us.

Parameters:

  • other (Class)

    the inheriting class



109
110
111
# File 'lib/sober_swag/reporting/input/struct.rb', line 109

def inherited(other)
  other.parent_struct = self unless self == SoberSwag::Reporting::Input::Struct
end

.input_typeSoberSwag::Reporting::Input::Base

Returns the type to use for input.

Returns:



117
118
119
# File 'lib/sober_swag/reporting/input/struct.rb', line 117

def input_type
  object_type.mapped { |x| new(x) }.referenced(identifier)
end

.make_input_type(name, input, block) ⇒ Object (private)

Raises:

  • (ArgumentError)


171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/sober_swag/reporting/input/struct.rb', line 171

def make_input_type(name, input, block)
  raise ArgumentError, 'cannot pass a block to make a sub-struct and a field type' if input && block

  return input if input

  raise ArgumentError, 'must pass an input type OR a block to make a sub-struct' unless block

  const_name = name.to_s.camelize

  raise ArgumentError, 'cannot define struct sub-type, constant already exists!' if const_defined?(const_name)

  Class.new(SoberSwag::Reporting::Input::Struct, &block).tap { |c| const_set(const_name, c) }
end

.object_propertiesHash<Symbol, Object::Property>

Get a list of properties defined by this instance.

Please do not mutate this, it will break everything.

Returns:



96
97
98
# File 'lib/sober_swag/reporting/input/struct.rb', line 96

def object_properties
  @object_properties ||= {}
end

.object_typeObject (private)



196
197
198
199
200
201
202
# File 'lib/sober_swag/reporting/input/struct.rb', line 196

def object_type
  if parent_struct.nil?
    Object.new(object_properties)
  else
    MergeObjects.new(parent_struct, Object.new(object_properties))
  end
end

.parse(json) ⇒ Object

See Also:

  • #call


145
146
147
# File 'lib/sober_swag/reporting/input/struct.rb', line 145

def parse(json)
  call(json)
end

.parse!(json) ⇒ Object

See Also:



151
152
153
# File 'lib/sober_swag/reporting/input/struct.rb', line 151

def parse!(json)
  call!(json)
end

.swagger_path_schemaObject



165
166
167
# File 'lib/sober_swag/reporting/input/struct.rb', line 165

def swagger_path_schema
  object_type.swagger_path_schema
end

.swagger_query_schemaObject



161
162
163
# File 'lib/sober_swag/reporting/input/struct.rb', line 161

def swagger_query_schema
  object_type.swagger_query_schema
end

.swagger_schemaArray[Hash, Hash]

Returns swagger schema type.

Returns:

  • (Array[Hash, Hash])

    swagger schema type.



157
158
159
# File 'lib/sober_swag/reporting/input/struct.rb', line 157

def swagger_schema
  input_type.swagger_schema
end

Instance Method Details

#<=>(other) ⇒ Object

Allow structs to be ordered like values.



237
238
239
240
241
# File 'lib/sober_swag/reporting/input/struct.rb', line 237

def <=>(other)
  return nil unless other.is_a?(self.class)

  ordered_values <=> other.ordered_values
end

#[](name) ⇒ Object



211
212
213
# File 'lib/sober_swag/reporting/input/struct.rb', line 211

def [](name)
  @struct_properties[name]
end

#eql?(other) ⇒ Boolean

Allow structs to be compared like values.

Returns:

  • (Boolean)


229
230
231
232
233
# File 'lib/sober_swag/reporting/input/struct.rb', line 229

def eql?(other)
  return false unless other.is_a?(self.class)

  ordered_values.eql?(other.ordered_values)
end

#hashObject

Hash code for this struct.



217
218
219
# File 'lib/sober_swag/reporting/input/struct.rb', line 217

def hash
  [self.class.hash, *ordered_values.hash].hash
end

#inspectObject



263
264
265
266
267
268
# File 'lib/sober_swag/reporting/input/struct.rb', line 263

def inspect
  keys = self.class.object_properties.keys.each.with_object([]) do |k, obj|
    obj << "#{k}=#{public_send(k).inspect}" if public_send(:"#{k}_present?")
  end
  "#<#{self.class.name || self.class.inspect[2..-2]} #{keys.join(' ')}>"
end

#ordered_valuesObject

Return an array of the values of this, in order.



223
224
225
# File 'lib/sober_swag/reporting/input/struct.rb', line 223

def ordered_values
  self.class.object_properties.keys.map { |k| @struct_properties[k] }
end

#to_hObject

Extracts the transformed struct properties.

Keys not present in the input will also not be present in this hash.



249
250
251
252
253
254
255
256
257
# File 'lib/sober_swag/reporting/input/struct.rb', line 249

def to_h
  @struct_properties.transform_values do |value|
    if value.is_a?(SoberSwag::Reporting::Input::Struct)
      value.to_h
    else
      value
    end
  end
end

#to_sObject



259
260
261
# File 'lib/sober_swag/reporting/input/struct.rb', line 259

def to_s
  inspect
end