-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move OAS creation logic to builders and replace common objects
by references to components.
- Loading branch information
Showing
27 changed files
with
701 additions
and
369 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
module OasRails | ||
module Builders | ||
class ContentBuilder | ||
def initialize(specification, context) | ||
@context = context || :incoming | ||
@specification = specification | ||
@media_type = Spec::MediaType.new(specification) | ||
end | ||
|
||
def with_schema(schema) | ||
@media_type.schema = @specification.components.add_schema(schema) | ||
|
||
self | ||
end | ||
|
||
def with_examples(examples) | ||
@media_type.examples = @specification.components.add_example(examples) | ||
|
||
self | ||
end | ||
|
||
def with_examples_from_tags(tags) | ||
@media_type.examples = @media_type.examples.merge(tags.each_with_object({}).with_index(1) do |(example, result), _index| | ||
key = example.text.downcase.gsub(' ', '_') | ||
value = { | ||
"summary" => example.text, | ||
"value" => example.content | ||
} | ||
result[key] = @specification.components.add_example(value) | ||
end) | ||
|
||
self | ||
end | ||
|
||
def from_model_class(klass) | ||
return self unless klass.ancestors.include? ActiveRecord::Base | ||
|
||
model_schema = EsquemaBuilder.send("build_#{@context}_schema", klass:) | ||
model_schema["required"] = [] | ||
schema = { type: "object", properties: { klass.to_s.downcase => model_schema } } | ||
examples = Spec::MediaType.search_for_examples_in_tests(klass, context: @context) | ||
@media_type.schema = @specification.components.add_schema(schema) | ||
@media_type.examples = @media_type.examples.merge(examples) | ||
|
||
self | ||
end | ||
|
||
def build | ||
{ | ||
"application/json": @media_type | ||
} | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module OasRails | ||
module Builders | ||
class OperationBuilder | ||
include Extractors::OasRouteExtractor | ||
|
||
def initialize(specification) | ||
@specification = specification | ||
@operation = Spec::Operation.new(specification) | ||
end | ||
|
||
def from_oas_route(oas_route) | ||
@operation.summary = extract_summary(oas_route:) | ||
@operation.operation_id = extract_operation_id(oas_route:) | ||
@operation.description = oas_route.docstring | ||
@operation.tags = extract_tags(oas_route:) | ||
@operation.security = extract_security(oas_route:) | ||
@operation.parameters = ParametersBuilder.new(@specification).from_oas_route(oas_route).build | ||
@operation.request_body = RequestBodyBuilder.new(@specification).from_oas_route(oas_route).reference | ||
@operation.responses = ResponsesBuilder.new(@specification).from_oas_route(oas_route).add_autodiscovered_responses(oas_route).build | ||
|
||
self | ||
end | ||
|
||
def build | ||
@operation | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module OasRails | ||
module Builders | ||
class ParameterBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@parameter = Spec::Parameter.new(specification) | ||
end | ||
|
||
def from_path(path, param) | ||
@parameter.name = param | ||
@parameter.in = 'path' | ||
@parameter.description = "#{param.split('_')[-1].titleize} of existing #{extract_word_before(path, param).singularize}." | ||
|
||
self | ||
end | ||
|
||
def extract_word_before(string, param) | ||
regex = %r{/(\w+)/\{#{param}\}} | ||
match = string.match(regex) | ||
match ? match[1] : nil | ||
end | ||
|
||
def build | ||
@parameter | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
module OasRails | ||
module Builders | ||
class ParametersBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@parameters = [] | ||
end | ||
|
||
def from_oas_route(oas_route) | ||
parameters_from_tags(tags: oas_route.docstring.tags(:parameter)) | ||
oas_route.path_params.try(:map) do |p| | ||
@parameters << ParameterBuilder.new(@specification).from_path(oas_route.path, p).build unless @parameters.any? { |param| param.name.to_s == p.to_s } | ||
end | ||
|
||
self | ||
end | ||
|
||
def parameters_from_tags(tags:) | ||
tags.each do |t| | ||
parameter = Spec::Parameter.new(@specification) | ||
parameter.name = t.name | ||
parameter.in = t.location | ||
parameter.required = t.required | ||
parameter.schema = t.schema | ||
parameter.description = t.text | ||
@parameters << parameter | ||
end | ||
|
||
self | ||
end | ||
|
||
def build | ||
@parameters.map do |p| | ||
@specification.components.add_parameter(p) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module OasRails | ||
module Builders | ||
class PathItemBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@path_item = Spec::PathItem.new(specification) | ||
end | ||
|
||
def from_path(path, route_extractor: Extractors::RouteExtractor) | ||
route_extractor.host_routes_by_path(path).each do |oas_route| | ||
@path_item.add_operation(oas_route.verb.downcase, OperationBuilder.new(@specification).from_oas_route(oas_route).build) | ||
end | ||
|
||
self | ||
end | ||
|
||
def build | ||
@path_item | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
module OasRails | ||
module Builders | ||
class RequestBodyBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@request_body = Spec::RequestBody.new(specification) | ||
end | ||
|
||
def from_oas_route(oas_route) | ||
tag_request_body = oas_route.docstring.tags(:request_body).first | ||
if tag_request_body.nil? && OasRails.config.autodiscover_request_body | ||
detect_request_body(oas_route) if %w[create update].include? oas_route.method | ||
elsif !tag_request_body.nil? | ||
from_tags(tag: tag_request_body, examples_tags: oas_route.docstring.tags(:request_body_example)) | ||
end | ||
|
||
self | ||
end | ||
|
||
def from_tags(tag:, examples_tags: []) | ||
if tag.klass.ancestors.include? ActiveRecord::Base | ||
from_model_class(klass: tag.klass, description: tag.text, required: tag.required, examples_tags:) | ||
else | ||
@request_body.description = tag.text | ||
@request_body.content = ContentBuilder.new(@specification, :incoming).with_schema(tag.schema).with_examples_from_tags(examples_tags).build | ||
@request_body.required = tag.required | ||
end | ||
|
||
self | ||
end | ||
|
||
def from_model_class(klass:, **kwargs) | ||
@request_body.description = kwargs[:description] || klass.to_s | ||
@request_body.content = ContentBuilder.new(@specification, :incoming).from_model_class(klass).with_examples_from_tags(kwargs[:examples_tags] || {}).build | ||
@request_body.required = kwargs[:required] | ||
|
||
self | ||
end | ||
|
||
def build | ||
return {} if @request_body.content == {} | ||
|
||
@request_body | ||
end | ||
|
||
def reference | ||
return {} if @request_body.content == {} | ||
|
||
@specification.components.add_request_body(@request_body) | ||
end | ||
|
||
private | ||
|
||
def detect_request_body(oas_route) | ||
klass = oas_route.controller.singularize.camelize.constantize | ||
from_model_class(klass:, required: true) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
module OasRails | ||
module Builders | ||
class ResponseBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@response = Spec::Response.new(specification) | ||
end | ||
|
||
def with_description(description) | ||
@response.description = description | ||
|
||
self | ||
end | ||
|
||
def with_content(content) | ||
@response.content = content | ||
|
||
self | ||
end | ||
|
||
def with_code(code) | ||
@response.code = code | ||
|
||
self | ||
end | ||
|
||
def from_tag(tag) | ||
@response.code = tag.name.to_i | ||
@response.description = tag.text | ||
@response.content = ContentBuilder.new(@specification, :outgoing).with_schema(tag.schema).build | ||
|
||
self | ||
end | ||
|
||
def build | ||
@response | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
module OasRails | ||
module Builders | ||
class ResponsesBuilder | ||
def initialize(specification) | ||
@specification = specification | ||
@responses = Spec::Responses.new(specification) | ||
end | ||
|
||
def from_oas_route(oas_route) | ||
oas_route.docstring.tags(:response).each do |tag| | ||
@responses.add_response(ResponseBuilder.new(@specification).from_tag(tag).build) | ||
end | ||
|
||
self | ||
end | ||
|
||
def add_autodiscovered_responses(oas_route) | ||
return unless OasRails.config.autodiscover_responses | ||
|
||
new_responses = Extractors::RenderResponseExtractor.extract_responses_from_source(@specification, source: oas_route.source_string) | ||
|
||
new_responses.each do |new_response| | ||
@responses.add_response(new_response) if @responses.responses[new_response.code].blank? | ||
end | ||
|
||
self | ||
end | ||
|
||
def build | ||
@responses | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.