Class: Jsapi::Meta::Definitions

Inherits:
Model::Base show all
Includes:
OpenAPI::Extensions
Defined in:
lib/jsapi/meta/definitions.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from OpenAPI::Extensions

included

Methods inherited from Model::Base

#inspect, #merge!, #reference?, #resolve

Methods included from Model::Attributes

#attributes_frozen?, #freeze_attributes, included

Constructor Details

#initialize(keywords = {}) ⇒ Definitions

Returns a new instance of Definitions.



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/jsapi/meta/definitions.rb', line 151

def initialize(keywords = {})
  keywords = keywords.dup
  @owner = keywords.delete(:owner)
  @parent = keywords.delete(:parent)
  included = keywords.delete(:include)
  super(keywords)

  Array(included).each do |definitions|
    include(definitions)
  end
  @parent&.inherited(self)
end

Instance Attribute Details

#ownerObject (readonly)

The class to which this instance is assigned.



146
147
148
# File 'lib/jsapi/meta/definitions.rb', line 146

def owner
  @owner
end

#parentObject (readonly)

The Definitions instance from which this instance inherits.



149
150
151
# File 'lib/jsapi/meta/definitions.rb', line 149

def parent
  @parent
end

Instance Method Details

#add_operation(name, parent_path = nil, keywords = {}) ⇒ Object

:nodoc:



164
165
166
167
168
169
170
171
172
173
# File 'lib/jsapi/meta/definitions.rb', line 164

def add_operation(name, parent_path = nil, keywords = {}) # :nodoc:
  try_modify_attribute!(:operations) do
    parent_path, keywords = nil, parent_path if parent_path.is_a?(Hash)

    name = name.nil? ? default_operation_name : name.to_s
    parent_path ||= default_operation_name unless keywords[:path].present?

    (@operations ||= {})[name] = Operation.new(name, parent_path, keywords)
  end
end

#add_parameter(name, keywords = {}) ⇒ Object

:nodoc:



175
176
177
178
179
180
181
# File 'lib/jsapi/meta/definitions.rb', line 175

def add_parameter(name, keywords = {}) # :nodoc:
  try_modify_attribute!(:parameters) do
    name = name.to_s

    (@parameters ||= {})[name] = Parameter.new(name, keywords)
  end
end

#add_path(name, keywords = {}) ⇒ Object

:nodoc:



183
184
185
186
187
188
189
# File 'lib/jsapi/meta/definitions.rb', line 183

def add_path(name, keywords = {}) # :nodoc:
  try_modify_attribute!(:paths) do
    pathname = Pathname.from(name)

    (@paths ||= {})[pathname] = Path.new(pathname, self, keywords)
  end
end

#ancestorsObject

Returns an array containing itself and all of the Definitions instances inherited or included.



193
194
195
196
197
198
199
# File 'lib/jsapi/meta/definitions.rb', line 193

def ancestors
  @ancestors ||= [self].tap do |ancestors|
    [@included_definitions, @parent].flatten.each do |definitions|
      ancestors.push(*definitions.ancestors) if definitions
    end
  end.uniq
end

#attribute_nameObject

:method: find_security_scheme Returns the security scheme with the specified name.



336
337
338
339
340
# File 'lib/jsapi/meta/definitions.rb', line 336

%i[parameters request_bodies responses schemas security_schemes].each do |attribute_name|
  define_method(:"find_#{attribute_name.to_s.singularize}") do |name|
    cached_attributes.dig(attribute_name, name&.to_s)
  end
end

#base_pathObject

:attr: base_path The base path of the API.

Applies to OpenAPI 2.0.



13
# File 'lib/jsapi/meta/definitions.rb', line 13

attribute :base_path, Pathname

#callbacksObject

:attr: callbacks The reusable callbacks. Maps strings to Callback objects or references.

Applies to OpenAPI 3.0 and higher.



20
# File 'lib/jsapi/meta/definitions.rb', line 20

attribute :callbacks, { String => Callback }

#default_security_requirementsObject

The security requirements that apply by default to all operations.



297
298
299
# File 'lib/jsapi/meta/definitions.rb', line 297

def default_security_requirements
  cached_attributes[:security_requirements]
end

#default_value(type, context: nil) ⇒ Object

Returns the default value for type within context.



292
293
294
# File 'lib/jsapi/meta/definitions.rb', line 292

def default_value(type, context: nil)
  cached_attributes.dig(:defaults, type.to_s)&.value(context: context)
end

#defaultsObject

:attr: defaults The registered default values for different schema types. Maps schema types to Defaults object.



26
# File 'lib/jsapi/meta/definitions.rb', line 26

attribute :defaults, { String => Defaults }, keys: Schema::TYPES

#examplesObject

:attr: examples The reusable examples. Maps example names to Example objects or references.

Applies to OpenAPI 3.0 and higher.



33
# File 'lib/jsapi/meta/definitions.rb', line 33

attribute :examples, { String => Example }

#external_docsObject

:attr: external_docs The ExternalDocumentation object.



38
# File 'lib/jsapi/meta/definitions.rb', line 38

attribute :external_docs, ExternalDocumentation

#find_operation(name = nil) ⇒ Object

Returns the operation with the specified name.



302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/jsapi/meta/definitions.rb', line 302

def find_operation(name = nil)
  name = name&.to_s

  cache_operation(name) do
    if name.present?
      # Select the operation with the given name
      cached_attributes.dig(:operations, name)
    elsif operations.one?
      # Select the one and only operation
      operations.values.first
    end
  end
end

#headersObject

:attr: headers The reusable headers. Maps header names to Header objects or references.

Applies to OpenAPI 3.0 and higher.



45
# File 'lib/jsapi/meta/definitions.rb', line 45

attribute :headers, { String => Header }

#hostObject

:attr: host The host serving the API.

Applies to OpenAPI 2.0.



52
# File 'lib/jsapi/meta/definitions.rb', line 52

attribute :host, String

#include(definitions) ⇒ Object

Includes definitions.



343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/jsapi/meta/definitions.rb', line 343

def include(definitions)
  if circular_dependency?(definitions)
    raise ArgumentError,
          'detected circular dependency between ' \
          "#{owner.inspect} and " \
          "#{definitions.owner.inspect}"
  end

  (@included_definitions ||= []) << definitions
  definitions.included(self)
  invalidate_ancestors
  self
end

#infoObject

:attr: info The Info object.



57
# File 'lib/jsapi/meta/definitions.rb', line 57

attribute :info, Info

#invalidate_ancestorsObject

Invalidates cached ancestors.



358
359
360
361
362
# File 'lib/jsapi/meta/definitions.rb', line 358

def invalidate_ancestors
  @ancestors = nil
  @cache = nil
  each_descendant(&:invalidate_ancestors)
end

#invalidate_attributesObject

Invalidates cached attributes.



365
366
367
368
# File 'lib/jsapi/meta/definitions.rb', line 365

def invalidate_attributes
  @cache = nil
  each_descendant(&:invalidate_attributes)
end

#invalidate_path_attribute(pathname, name) ⇒ Object

Invalidates the given path attribute.



371
372
373
374
375
376
377
378
379
380
381
# File 'lib/jsapi/meta/definitions.rb', line 371

def invalidate_path_attribute(pathname, name)
  pathname = Pathname.from(pathname)
  name = name.to_sym

  cached_path_attributes.fetch(pathname, nil)&.delete(name)
  @cache[:operations] = nil

  each_descendant do |descendant|
    descendant.invalidate_path_attribute(pathname, name)
  end
end

#json_schema_document(name) ⇒ Object

Returns a hash representing the JSON Schema document for name.



384
385
386
387
388
389
390
# File 'lib/jsapi/meta/definitions.rb', line 384

def json_schema_document(name)
  find_schema(name)&.to_json_schema&.tap do |json_schema_document|
    if (schemas = cached_attributes[:schemas].except(name.to_s)).any?
      json_schema_document[:definitions] = schemas.transform_values(&:to_json_schema)
    end
  end&.as_json
end

:attr: links The reusable links. Maps link names to Link objects.

Applies to OpenAPI 3.0 and higher.



64
# File 'lib/jsapi/meta/definitions.rb', line 64

attribute :links, { String => Link }

#nameObject

:method: common_tags :args: pathname Returns the tags that apply to all operations in the specified path.



226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/jsapi/meta/definitions.rb', line 226

%i[description model request_body servers summary].each do |name|
  define_method(:"common_#{name}") do |arg|
    arg = Pathname.from(arg || '')

    cache_path_attribute(arg, name) do
      arg.ancestors.lazy.filter_map do |pathname|
        ancestors.lazy.filter_map do |definitions|
          definitions.path(pathname)&.public_send(name).presence
        end.first
      end.first
    end
  end
end

#on_rescue_callbacksObject

Returns the methods or procs to be called when rescuing an exception.



393
394
395
# File 'lib/jsapi/meta/definitions.rb', line 393

def on_rescue_callbacks
  cached_attributes[:on_rescues]
end

#on_rescuesObject

:attr: on_rescues The methods or procs to be called whenever an exception is rescued.



69
# File 'lib/jsapi/meta/definitions.rb', line 69

attribute :on_rescues, []

#openapi_document(version = nil) ⇒ Object

Returns a hash representing the OpenAPI document for version.

Raises an ArgumentError if version is not supported.



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# File 'lib/jsapi/meta/definitions.rb', line 400

def openapi_document(version = nil)
  version = OpenAPI::Version.from(version)
  operations = cached_attributes[:operations].values

  openapi_paths = operations.group_by(&:full_path).to_h do |key, value|
    [
      key,
      OpenAPI::PathItem.new(
        value,
        description: common_description(key),
        parameters: common_parameters(key),
        summary: common_summary(key),
        servers: common_servers(key)
      ).to_openapi(version, self)
    ]
  end.presence

  openapi_objects = (
    %i[external_docs info parameters responses schemas
       security_requirements security_schemes tags] +
    if version == OpenAPI::V2_0
      %i[base_path host schemes]
    else
      %i[callbacks examples headers links request_bodies servers]
    end
  ).index_with do |key|
    value = cached_attributes[key]
    if key == :responses
      value = value.reject do |_name, response|
        response.resolve(self).nodoc?
      end
    end
    object_to_openapi(value, version).presence
  end

  with_openapi_extensions(
    if version == OpenAPI::V2_0
      openapi_server = cached_attributes[:servers].first || default_server
      uri = URI(openapi_server.url) if openapi_server
      {
        # Order according to the OpenAPI specification 2.x
        swagger: '2.0',
        info: openapi_objects[:info],
        host: openapi_objects[:host] || uri&.hostname,
        basePath: openapi_objects[:base_path] || uri&.path,
        schemes: openapi_objects[:schemes] || Array(uri&.scheme).presence,
        consumes:
          Media::Range.reduce(
            operations.filter_map do |operation|
              operation.request_body&.resolve(self)&.default_media_range
            end
          ).presence,
        produces:
          operations.flat_map do |operation|
            operation.responses.values.filter_map do |response|
              response = response.resolve(self)
              response.default_media_type unless response.nodoc?
            end
          end.uniq.sort.presence,
        paths: openapi_paths,
        definitions: openapi_objects[:schemas],
        parameters: openapi_objects[:parameters],
        responses: openapi_objects[:responses],
        securityDefinitions: openapi_objects[:security_schemes]
      }
    else
      {
        # Order according to the OpenAPI specification 3.x
        openapi: version,
        info: openapi_objects[:info],
        servers:
          openapi_objects[:servers] ||
          [default_server&.to_openapi(version)].compact.presence,
        paths: openapi_paths,
        components: {
          schemas: openapi_objects[:schemas],
          responses: openapi_objects[:responses],
          parameters: openapi_objects[:parameters],
          examples: openapi_objects[:examples],
          requestBodies: openapi_objects[:request_bodies],
          headers: openapi_objects[:headers],
          securitySchemes: openapi_objects[:security_schemes],
          links: openapi_objects[:links],
          callbacks: openapi_objects[:callbacks]
        }.compact.presence
      }
    end.merge(
      security: openapi_objects[:security_requirements],
      tags: openapi_objects[:tags],
      externalDocs: openapi_objects[:external_docs]
    ).compact
  ).as_json
end

#operationsObject

:attr: operations The operations. Maps operation names to Operation objects.



74
# File 'lib/jsapi/meta/definitions.rb', line 74

attribute :operations, { String => Operation }, accessors: %i[reader writer]

#parametersObject

:attr: parameters The reusable parameters. Maps parameter names to Parameter objects or references.



80
# File 'lib/jsapi/meta/definitions.rb', line 80

attribute :parameters, { String => Parameter }, accessors: %i[reader writer]

#pathsObject

:attr: paths The paths. Maps instances of Pathname to Path objects.



85
# File 'lib/jsapi/meta/definitions.rb', line 85

attribute :paths, { Pathname => Path }, accessors: %i[reader writer]

#request_bodiesObject

:attr: request_bodies The reusable request bodies. Maps request body names to RequestBody objects or references.



96
# File 'lib/jsapi/meta/definitions.rb', line 96

attribute :request_bodies, { String => RequestBody }

#rescue_handler_for(exception) ⇒ Object

Returns the first RescueHandler capable to handle exception, or nil if no one could be found.



496
497
498
# File 'lib/jsapi/meta/definitions.rb', line 496

def rescue_handler_for(exception)
  cached_attributes[:rescue_handlers].find { |r| r.match?(exception) }
end

#rescue_handlersObject

:attr: rescue_handlers The registered rescue handlers.



90
# File 'lib/jsapi/meta/definitions.rb', line 90

attribute :rescue_handlers, [RescueHandler]

#responsesObject

:attr: responses The reusable responses. Maps response names to Response objects or references.



102
# File 'lib/jsapi/meta/definitions.rb', line 102

attribute :responses, { String => Response }

#schemasObject

:attr: schemas The reusable schemas. Maps schema names to Schema objects or references.



107
# File 'lib/jsapi/meta/definitions.rb', line 107

attribute :schemas, { String => Schema }

#schemesObject

:attr: schemes The transfer protocols supported by the API. Can contain one or more of:

  • "http"

  • "https"

  • "ws"

  • "wss"

Applies to OpenAPI 2.0.



119
# File 'lib/jsapi/meta/definitions.rb', line 119

attribute :schemes, [String], values: %w[http https ws wss]

#security_requirementsObject

:attr: security_requirements The top-level security requirements.



124
# File 'lib/jsapi/meta/definitions.rb', line 124

attribute :security_requirements, [SecurityRequirement]

#security_schemesObject

:attr: security_schemes The security schemes.



131
# File 'lib/jsapi/meta/definitions.rb', line 131

attribute :security_schemes, { String => SecurityScheme }

#serversObject

:attr: servers The servers providing the API.

Applies to OpenAPI 3.0 and higher.



138
# File 'lib/jsapi/meta/definitions.rb', line 138

attribute :servers, [Server]

#tagsObject

:attr: tags The tags.



143
# File 'lib/jsapi/meta/definitions.rb', line 143

attribute :tags, [Tag]