Class: SoberSwag::Reporting::Output::Struct
- Inherits:
-
Object
- Object
- SoberSwag::Reporting::Output::Struct
- Extended by:
- Interface
- Defined in:
- lib/sober_swag/reporting/output/struct.rb
Overview
A DSL for building "output object structs."
Class Attribute Summary collapse
-
.parent_struct ⇒ Object
Returns the value of attribute parent_struct.
Instance Attribute Summary collapse
-
#_struct_serialized ⇒ Object
readonly
Returns the value of attribute _struct_serialized.
Class Method Summary collapse
- .bad_field_message(name, field_type) ⇒ Object private
-
.call(value, view: :base) ⇒ Hash
Serialize an object to a hash.
- .define_field(method, extractor) ⇒ Object private
-
.define_inherited_view(name, inherits:, &block) ⇒ Class
Defines a view for this object, which "inherits" another view.
-
.define_view(name, &block) ⇒ Class
Define a view for this object.
- .define_view_with_parent(name, parent, block) ⇒ Object private
-
.description(val = nil) ⇒ String
Set a description for the type of this output.
-
.field(name, output, description: nil, &extract) ⇒ Object
Define a new field to be serialized.
- .identified_view_map ⇒ Object private
-
.identified_with_base ⇒ Interface
Used to generate 'allOf' subtyping relationships.
-
.identified_without_base ⇒ Object
Used to generate 'allOf' subtyping relationships.
-
.identifier(value = nil) ⇒ String
Set a new identifier for this output object.
-
.inherited(other) ⇒ Object
When this class is inherited, it sets up a future subtyping relationship.
-
.inherited_output ⇒ Interface
Used to generate 'allOf' subtyping relationships.
-
.object_fields ⇒ Hash<Symbol, Object::Property>
The properties defined directly on this object.
- .object_output ⇒ Object
-
.serialize_report(value, view: :base) ⇒ Hash
Serialize an object to a hash, with type-checking.
-
.single_output ⇒ Object
An output for this specific schema type.
-
.swagger_schema ⇒ Object
Schema for this output.
-
.view(name) ⇒ Interface
A serializer suitable for this interface.
-
.view_class(name) ⇒ Class
Equivalent to .view, but returns the raw view class.
- .view_map ⇒ Object
-
.views ⇒ Set<Symbol>
All applicable views.
Instance Method Summary collapse
-
#initialize(struct_serialized) ⇒ Struct
constructor
A new instance of Struct.
-
#object_to_serialize ⇒ Object
The object to serialize.
Methods included from Interface
call!, described, enum, in_range, list, nilable, partitioned, referenced, reporting?, serialize, via_map
Constructor Details
#initialize(struct_serialized) ⇒ Struct
Returns a new instance of Struct.
280 281 282 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 280 def initialize(struct_serialized) @_struct_serialized = struct_serialized end |
Class Attribute Details
.parent_struct ⇒ Object
Returns the value of attribute parent_struct.
212 213 214 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 212 def parent_struct @parent_struct end |
Instance Attribute Details
#_struct_serialized ⇒ Object (readonly)
Returns the value of attribute _struct_serialized.
284 285 286 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 284 def _struct_serialized @_struct_serialized end |
Class Method Details
.bad_field_message(name, field_type) ⇒ Object (private)
239 240 241 242 243 244 245 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 239 def (name, field_type) [ "Output type used for field #{name.inspect} was", "#{field_type.inspect}, which is not an instance of", SoberSwag::Reporting::Output::Interface.name ].join(' ') end |
.call(value, view: :base) ⇒ Hash
Serialize an object to a hash.
126 127 128 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 126 def call(value, view: :base) view(view).output.call(value) end |
.define_field(method, extractor) ⇒ Object (private)
266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 266 def define_field(method, extractor) e = if extractor.nil? proc { _struct_serialized.public_send(method) } elsif extractor.arity == 1 proc { extractor.call(_struct_serialized) } else extractor end define_method(method, &e) end |
.define_inherited_view(name, inherits:, &block) ⇒ Class
Defines a view for this object, which "inherits" another view.
175 176 177 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 175 def define_inherited_view(name, inherits:, &block) define_view_with_parent(name, view_class(inherits), block) end |
.define_view(name, &block) ⇒ Class
Define a view for this object.
Views behave like their own output structs, which inherit the parent (or 'base' view). This means that fields after the definition of a view will be present in the view. This enables views to maintain a subtyping relationship.
Your base view should thus serialize as little as possible.
View classes get defined as child constants.
So, if I write define_view(:foo)
on a struct called Person
,
I will get Person::Foo
as a class I can use if I want!
163 164 165 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 163 def define_view(name, &block) define_view_with_parent(name, self, block) end |
.define_view_with_parent(name, parent, block) ⇒ Object (private)
247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 247 def define_view_with_parent(name, parent, block) raise ArgumentError, "duplicate view #{name}" if name == :base || views.include?(name) classy_name = name.to_s.classify us = self # grab this so its identifier doesn't get nested under whatever parent it inherits from, since its our view Class.new(parent).tap do |c| c.instance_eval(&block) c.define_singleton_method(:define_view) { |*| raise ArgumentError, 'no nesting views' } c.define_singleton_method(:identifier) { [us.identifier, classy_name.gsub('::', '.')].join('.') } const_set(classy_name, c) view_map[name] = c end end |
.description(val = nil) ⇒ String
Set a description for the type of this output. It will show up as a description in the component key for this output. Right now that unfortunately will not render with ReDoc, but it should eventually.
49 50 51 52 53 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 49 def description(val = nil) return @description unless val @description = val end |
.field(name, output, description: nil, &extract) ⇒ Object
Define a new field to be serialized.
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 22 def field(name, output, description: nil, &extract) raise ArgumentError, (name, output) unless output.is_a?(Interface) define_field(name, extract) object_fields[name] = Object::Property.new( output.view(:base).via_map(&name.to_proc), description: description ) end |
.identified_view_map ⇒ Object (private)
262 263 264 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 262 def identified_view_map view_map.transform_values(&:identified_without_base).merge(base: inherited_output) end |
.identified_with_base ⇒ Interface
Used to generate 'allOf' subtyping relationships. Probably do not call this yourself.
74 75 76 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 74 def identified_with_base object_output.referenced([identifier, 'Base'].join('.')) end |
.identified_without_base ⇒ Object
Used to generate 'allOf' subtyping relationships. Probably do not call this yourself.
81 82 83 84 85 86 87 88 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 81 def identified_without_base if parent_struct MergeObjects .new(parent_struct.inherited_output, object_output) else object_output end.referenced(identifier) end |
.identifier(value = nil) ⇒ String
Set a new identifier for this output object.
229 230 231 232 233 234 235 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 229 def identifier(value = nil) if value @identifier = value else @identifier || name&.gsub('::', '.') end end |
.inherited(other) ⇒ Object
When this class is inherited, it sets up a future subtyping relationship. This gets expressed with 'allOf' in the generated swagger.
217 218 219 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 217 def inherited(other) other.parent_struct = self unless self == ::SoberSwag::Reporting::Output::Struct end |
.inherited_output ⇒ Interface
Used to generate 'allOf' subtyping relationships. Probably do not call this yourself! Use #single_output instead.
This allows us to implement inheritance. So, if you inherit from another output object struct, you get its methods and attributes. Views behave as if they have inherited the base object.
This means that any views added to any parent output objects will be visible in children.
101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 101 def inherited_output inherited = if parent_struct MergeObjects .new(parent_struct.inherited_output, object_output) else object_output end identifier ? inherited.referenced([identifier, 'Base'].join('.')) : inherited end |
.object_fields ⇒ Hash<Symbol, Object::Property>
Returns the properties defined directly on this object. Does not include inherited fields!.
143 144 145 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 143 def object_fields @object_fields ||= {} end |
.object_output ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 33 def object_output base = Object.new(object_fields).via_map { |o| new(o) } if description base.described(description) else base end end |
.serialize_report(value, view: :base) ⇒ Hash
Serialize an object to a hash, with type-checking.
136 137 138 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 136 def serialize_report(value, view: :base) view(view).output.serialize_report(value) end |
.single_output ⇒ Object
An output for this specific schema type. If this schema has any views, it will be defined as a map of possible views to the actual views used. Otherwise, it will directly be the base definition.
59 60 61 62 63 64 65 66 67 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 59 def single_output single = if view_map.any? Viewed.new(identified_view_map) else inherited_output end identifier ? single.referenced(identifier) : single end |
.swagger_schema ⇒ Object
Schema for this output. Will include views, if applicable.
116 117 118 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 116 def swagger_schema single_output.swagger_schema end |
.view(name) ⇒ Interface
Returns a serializer suitable for this interface.
196 197 198 199 200 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 196 def view(name) return inherited_output if name == :base view_map.fetch(name).view(:base) end |
.view_class(name) ⇒ Class
Equivalent to .view, but returns the raw view class.
206 207 208 209 210 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 206 def view_class(name) return self if name == :base view_map.fetch(name) end |
.view_map ⇒ Object
182 183 184 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 182 def view_map @view_map ||= {} end |
.views ⇒ Set<Symbol>
Returns all applicable views.
Will always include :base
.
189 190 191 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 189 def views [:base, *view_map.keys].to_set end |
Instance Method Details
#object_to_serialize ⇒ Object
The object to serialize. Use this if you're defining your own methods.
289 290 291 |
# File 'lib/sober_swag/reporting/output/struct.rb', line 289 def object_to_serialize @_struct_serialized end |