oas_rails 0.2.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/app/controllers/oas_rails/oas_rails_controller.rb +1 -1
- data/lib/generators/oas_rails/config/templates/oas_rails_initializer.rb +11 -0
- data/lib/oas_rails/builders/content_builder.rb +55 -0
- data/lib/oas_rails/builders/operation_builder.rb +32 -0
- data/lib/oas_rails/builders/parameter_builder.rb +28 -0
- data/lib/oas_rails/builders/parameters_builder.rb +39 -0
- data/lib/oas_rails/builders/path_item_builder.rb +22 -0
- data/lib/oas_rails/builders/request_body_builder.rb +60 -0
- data/lib/oas_rails/builders/response_builder.rb +40 -0
- data/lib/oas_rails/builders/responses_builder.rb +58 -0
- data/lib/oas_rails/configuration.rb +25 -5
- data/lib/oas_rails/esquema_builder.rb +37 -0
- data/lib/oas_rails/extractors/oas_route_extractor.rb +66 -0
- data/lib/oas_rails/extractors/render_response_extractor.rb +148 -0
- data/lib/oas_rails/extractors/route_extractor.rb +125 -0
- data/lib/oas_rails/oas_route.rb +1 -99
- data/lib/oas_rails/spec/components.rb +85 -0
- data/lib/oas_rails/spec/contact.rb +18 -0
- data/lib/oas_rails/spec/hashable.rb +39 -0
- data/lib/oas_rails/{info.rb → spec/info.rb} +30 -24
- data/lib/oas_rails/spec/license.rb +18 -0
- data/lib/oas_rails/spec/media_type.rb +84 -0
- data/lib/oas_rails/spec/operation.rb +25 -0
- data/lib/oas_rails/spec/parameter.rb +34 -0
- data/lib/oas_rails/spec/path_item.rb +33 -0
- data/lib/oas_rails/spec/paths.rb +26 -0
- data/lib/oas_rails/spec/reference.rb +16 -0
- data/lib/oas_rails/spec/request_body.rb +21 -0
- data/lib/oas_rails/spec/response.rb +20 -0
- data/lib/oas_rails/spec/responses.rb +25 -0
- data/lib/oas_rails/spec/server.rb +17 -0
- data/lib/oas_rails/spec/specable.rb +51 -0
- data/lib/oas_rails/spec/specification.rb +50 -0
- data/lib/oas_rails/spec/tag.rb +18 -0
- data/lib/oas_rails/utils.rb +39 -0
- data/lib/oas_rails/version.rb +1 -1
- data/lib/oas_rails.rb +47 -26
- metadata +32 -18
- data/lib/oas_rails/contact.rb +0 -12
- data/lib/oas_rails/license.rb +0 -11
- data/lib/oas_rails/media_type.rb +0 -76
- data/lib/oas_rails/oas_base.rb +0 -30
- data/lib/oas_rails/operation.rb +0 -134
- data/lib/oas_rails/parameter.rb +0 -47
- data/lib/oas_rails/path_item.rb +0 -25
- data/lib/oas_rails/paths.rb +0 -19
- data/lib/oas_rails/request_body.rb +0 -29
- data/lib/oas_rails/response.rb +0 -12
- data/lib/oas_rails/responses.rb +0 -20
- data/lib/oas_rails/route_extractor.rb +0 -119
- data/lib/oas_rails/server.rb +0 -10
- data/lib/oas_rails/specification.rb +0 -72
- data/lib/oas_rails/tag.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 785755b5aed419ca89dc279c2965e5de19cc32bfcbd444a6cb2d25da2704fc8c
|
4
|
+
data.tar.gz: 774eac0d5dfb757e23b40c2ce90a1eab929615241109824b86696e481b06ab99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58ce0d42fa52b4bbc2c2d5c3bf81e3f23f0e859c62eb2145b63376873ca405f8ee6325b2c447a28b2cd4abd94e74af96986de96fc5ab2c5422b0a8e80a3e83a9
|
7
|
+
data.tar.gz: 537809a2b7dc85e3d66d1d0c06fd677527e06cc6fb5ba390189cc909dc8c912511677ad5686904e0636254b7d78a79cec85bff7ac4a1ae49a2e7c330a7a87aaf
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
OasRails is a Rails engine for generating **automatic interactive documentation for your Rails APIs**. It generates an **OAS 3.1** document and displays it using **[RapiDoc](https://rapidocweb.com)**.
|
8
8
|
|
9
|
-
![Screenshot](https://
|
9
|
+
![Screenshot](https://a-chacon.com/assets/images/oas_rails_ui.png)
|
10
10
|
|
11
11
|
## Related Projects
|
12
12
|
|
@@ -39,6 +39,7 @@ The goal is to minimize the effort required to create comprehensive documentatio
|
|
39
39
|
- [Tag Information](#tag-information)
|
40
40
|
- [Optional Settings](#optional-settings)
|
41
41
|
- [Authentication Settings](#authentication-settings)
|
42
|
+
- [Default Responses (Errors)](#default-responses)
|
42
43
|
- [Usage](#usage)
|
43
44
|
- [Documenting Your Endpoints](#documenting-your-endpoints)
|
44
45
|
- [Example](#example-of-documented-endpoints)
|
@@ -110,6 +111,14 @@ Then fill it with your data. Below are the available configuration options:
|
|
110
111
|
- `config.security_schema`: The default security schema used for authentication. Choose a predefined security schema from `[:api_key_cookie, :api_key_header, :api_key_query, :basic, :bearer, :bearer_jwt, :mutual_tls]`.
|
111
112
|
- `config.security_schemas`: Custom security schemas. Follow the [OpenAPI Specification](https://spec.openapis.org/oas/latest.html#security-scheme-object) for defining these schemas.
|
112
113
|
|
114
|
+
### Default Errors
|
115
|
+
|
116
|
+
- `config.set_default_responses`: Determines whether to add default errors responses to endpoint. Default is `true`.
|
117
|
+
|
118
|
+
- `config.possible_default_responses`: Array with possible default errors.(Some will be added depending on the endpoint, example: not_found only works with show/update/delete). Default: [:not_found, :unauthorized, :forbidden]. It should be HTTP status code symbols from the list: `[:not_found, :unauthorized, :forbidden, :internal_server_error, :unprocessable_entity]`
|
119
|
+
|
120
|
+
- `config.response_body_of_default`: body for use in default responses. It must be a Hash. Default: { message: String }
|
121
|
+
|
113
122
|
## Usage
|
114
123
|
|
115
124
|
In addition to the information provided in the initializer file and the data that can be extracted from the routes and methods automatically, it is essential to document your API in the following way. The documentation is created **with the help of YARD**, so the methods are documented with **comment tags**.
|
@@ -86,4 +86,15 @@ OasRails.configure do |config|
|
|
86
86
|
# "in": "header"
|
87
87
|
# }
|
88
88
|
# }
|
89
|
+
|
90
|
+
# ###########################
|
91
|
+
# Default Responses (Errors)
|
92
|
+
# ###########################
|
93
|
+
|
94
|
+
# The default responses errors are setted only if the action allow it.
|
95
|
+
# Example, if you add forbidden then it will be added only if the endpoint requires authentication.
|
96
|
+
# Example: not_found will be setted to the endpoint only if the operation is a show/update/destroy action.
|
97
|
+
# config.set_default_responses = true
|
98
|
+
# config.possible_default_responses = [:not_found, :unauthorized, :forbidden]
|
99
|
+
# config.response_body_of_default = { message: String }
|
89
100
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class ContentBuilder
|
4
|
+
def initialize(specification, context)
|
5
|
+
@context = context || :incoming
|
6
|
+
@specification = specification
|
7
|
+
@media_type = Spec::MediaType.new(specification)
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_schema(schema)
|
11
|
+
@media_type.schema = @specification.components.add_schema(schema)
|
12
|
+
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_examples(examples)
|
17
|
+
@media_type.examples = @specification.components.add_example(examples)
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_examples_from_tags(tags)
|
23
|
+
@media_type.examples = @media_type.examples.merge(tags.each_with_object({}).with_index(1) do |(example, result), _index|
|
24
|
+
key = example.text.downcase.gsub(' ', '_')
|
25
|
+
value = {
|
26
|
+
"summary" => example.text,
|
27
|
+
"value" => example.content
|
28
|
+
}
|
29
|
+
result[key] = @specification.components.add_example(value)
|
30
|
+
end)
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def from_model_class(klass)
|
36
|
+
return self unless klass.ancestors.include? ActiveRecord::Base
|
37
|
+
|
38
|
+
model_schema = EsquemaBuilder.send("build_#{@context}_schema", klass:)
|
39
|
+
model_schema["required"] = []
|
40
|
+
schema = { type: "object", properties: { klass.to_s.downcase => model_schema } }
|
41
|
+
examples = Spec::MediaType.search_for_examples_in_tests(klass, context: @context)
|
42
|
+
@media_type.schema = @specification.components.add_schema(schema)
|
43
|
+
@media_type.examples = @media_type.examples.merge(examples)
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def build
|
49
|
+
{
|
50
|
+
"application/json": @media_type
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class OperationBuilder
|
4
|
+
include Extractors::OasRouteExtractor
|
5
|
+
|
6
|
+
def initialize(specification)
|
7
|
+
@specification = specification
|
8
|
+
@operation = Spec::Operation.new(specification)
|
9
|
+
end
|
10
|
+
|
11
|
+
def from_oas_route(oas_route)
|
12
|
+
@operation.summary = extract_summary(oas_route:)
|
13
|
+
@operation.operation_id = extract_operation_id(oas_route:)
|
14
|
+
@operation.description = oas_route.docstring
|
15
|
+
@operation.tags = extract_tags(oas_route:)
|
16
|
+
@operation.security = extract_security(oas_route:)
|
17
|
+
@operation.parameters = ParametersBuilder.new(@specification).from_oas_route(oas_route).build
|
18
|
+
@operation.request_body = RequestBodyBuilder.new(@specification).from_oas_route(oas_route).reference
|
19
|
+
@operation.responses = ResponsesBuilder.new(@specification)
|
20
|
+
.from_oas_route(oas_route)
|
21
|
+
.add_autodiscovered_responses(oas_route)
|
22
|
+
.add_default_responses(oas_route, !@operation.security.empty?).build
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def build
|
28
|
+
@operation
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class ParameterBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@parameter = Spec::Parameter.new(specification)
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_path(path, param)
|
10
|
+
@parameter.name = param
|
11
|
+
@parameter.in = 'path'
|
12
|
+
@parameter.description = "#{param.split('_')[-1].titleize} of existing #{extract_word_before(path, param).singularize}."
|
13
|
+
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def extract_word_before(string, param)
|
18
|
+
regex = %r{/(\w+)/\{#{param}\}}
|
19
|
+
match = string.match(regex)
|
20
|
+
match ? match[1] : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def build
|
24
|
+
@parameter
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class ParametersBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@parameters = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_oas_route(oas_route)
|
10
|
+
parameters_from_tags(tags: oas_route.docstring.tags(:parameter))
|
11
|
+
oas_route.path_params.try(:map) do |p|
|
12
|
+
@parameters << ParameterBuilder.new(@specification).from_path(oas_route.path, p).build unless @parameters.any? { |param| param.name.to_s == p.to_s }
|
13
|
+
end
|
14
|
+
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def parameters_from_tags(tags:)
|
19
|
+
tags.each do |t|
|
20
|
+
parameter = Spec::Parameter.new(@specification)
|
21
|
+
parameter.name = t.name
|
22
|
+
parameter.in = t.location
|
23
|
+
parameter.required = t.required
|
24
|
+
parameter.schema = t.schema
|
25
|
+
parameter.description = t.text
|
26
|
+
@parameters << parameter
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def build
|
33
|
+
@parameters.map do |p|
|
34
|
+
@specification.components.add_parameter(p)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class PathItemBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@path_item = Spec::PathItem.new(specification)
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_path(path, route_extractor: Extractors::RouteExtractor)
|
10
|
+
route_extractor.host_routes_by_path(path).each do |oas_route|
|
11
|
+
@path_item.add_operation(oas_route.verb.downcase, OperationBuilder.new(@specification).from_oas_route(oas_route).build)
|
12
|
+
end
|
13
|
+
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def build
|
18
|
+
@path_item
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class RequestBodyBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@request_body = Spec::RequestBody.new(specification)
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_oas_route(oas_route)
|
10
|
+
tag_request_body = oas_route.docstring.tags(:request_body).first
|
11
|
+
if tag_request_body.nil? && OasRails.config.autodiscover_request_body
|
12
|
+
detect_request_body(oas_route) if %w[create update].include? oas_route.method
|
13
|
+
elsif !tag_request_body.nil?
|
14
|
+
from_tags(tag: tag_request_body, examples_tags: oas_route.docstring.tags(:request_body_example))
|
15
|
+
end
|
16
|
+
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def from_tags(tag:, examples_tags: [])
|
21
|
+
if tag.klass.ancestors.include? ActiveRecord::Base
|
22
|
+
from_model_class(klass: tag.klass, description: tag.text, required: tag.required, examples_tags:)
|
23
|
+
else
|
24
|
+
@request_body.description = tag.text
|
25
|
+
@request_body.content = ContentBuilder.new(@specification, :incoming).with_schema(tag.schema).with_examples_from_tags(examples_tags).build
|
26
|
+
@request_body.required = tag.required
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def from_model_class(klass:, **kwargs)
|
33
|
+
@request_body.description = kwargs[:description] || klass.to_s
|
34
|
+
@request_body.content = ContentBuilder.new(@specification, :incoming).from_model_class(klass).with_examples_from_tags(kwargs[:examples_tags] || {}).build
|
35
|
+
@request_body.required = kwargs[:required]
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def build
|
41
|
+
return {} if @request_body.content == {}
|
42
|
+
|
43
|
+
@request_body
|
44
|
+
end
|
45
|
+
|
46
|
+
def reference
|
47
|
+
return {} if @request_body.content == {}
|
48
|
+
|
49
|
+
@specification.components.add_request_body(@request_body)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def detect_request_body(oas_route)
|
55
|
+
klass = oas_route.controller.singularize.camelize.constantize
|
56
|
+
from_model_class(klass:, required: true)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class ResponseBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@response = Spec::Response.new(specification)
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_description(description)
|
10
|
+
@response.description = description
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_content(content)
|
16
|
+
@response.content = content
|
17
|
+
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_code(code)
|
22
|
+
@response.code = code
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_tag(tag)
|
28
|
+
@response.code = tag.name.to_i
|
29
|
+
@response.description = tag.text
|
30
|
+
@response.content = ContentBuilder.new(@specification, :outgoing).with_schema(tag.schema).build
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def build
|
36
|
+
@response
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Builders
|
3
|
+
class ResponsesBuilder
|
4
|
+
def initialize(specification)
|
5
|
+
@specification = specification
|
6
|
+
@responses = Spec::Responses.new(specification)
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_oas_route(oas_route)
|
10
|
+
oas_route.docstring.tags(:response).each do |tag|
|
11
|
+
@responses.add_response(ResponseBuilder.new(@specification).from_tag(tag).build)
|
12
|
+
end
|
13
|
+
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_autodiscovered_responses(oas_route)
|
18
|
+
return unless OasRails.config.autodiscover_responses
|
19
|
+
|
20
|
+
new_responses = Extractors::RenderResponseExtractor.extract_responses_from_source(@specification, source: oas_route.source_string)
|
21
|
+
|
22
|
+
new_responses.each do |new_response|
|
23
|
+
@responses.add_response(new_response) if @responses.responses[new_response.code].blank?
|
24
|
+
end
|
25
|
+
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_default_responses(oas_route, security)
|
30
|
+
return unless OasRails.config.set_default_responses
|
31
|
+
|
32
|
+
content = ContentBuilder.new(@specification, :outgoing).with_schema(Utils.hash_to_json_schema(OasRails.config.response_body_of_default)).build
|
33
|
+
common_errors = []
|
34
|
+
common_errors.push(:unauthorized, :forbidden) if security
|
35
|
+
|
36
|
+
case oas_route.method
|
37
|
+
when "show", "update", "destroy"
|
38
|
+
common_errors.push(:not_found)
|
39
|
+
when "create", "index"
|
40
|
+
# possible errors for this methods?
|
41
|
+
end
|
42
|
+
|
43
|
+
(OasRails.config.possible_default_responses & common_errors).each do |e|
|
44
|
+
code = Utils.status_to_integer(e)
|
45
|
+
response = ResponseBuilder.new(@specification).with_code(code).with_description(Utils.get_definition(code)).with_content(content).build
|
46
|
+
|
47
|
+
@responses.add_response(response) if @responses.responses[response.code].blank?
|
48
|
+
end
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def build
|
54
|
+
@responses
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,10 +1,19 @@
|
|
1
1
|
module OasRails
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :info,
|
3
|
+
attr_accessor :info,
|
4
|
+
:default_tags_from,
|
5
|
+
:autodiscover_request_body,
|
6
|
+
:autodiscover_responses,
|
7
|
+
:api_path,
|
8
|
+
:security_schemas,
|
9
|
+
:authenticate_all_routes_by_default,
|
10
|
+
:set_default_responses,
|
11
|
+
:possible_default_responses,
|
12
|
+
:response_body_of_default
|
4
13
|
attr_reader :servers, :tags, :security_schema
|
5
14
|
|
6
15
|
def initialize
|
7
|
-
@info = Info.new
|
16
|
+
@info = Spec::Info.new
|
8
17
|
@servers = default_servers
|
9
18
|
@tags = []
|
10
19
|
@swagger_version = '3.1.0'
|
@@ -15,6 +24,9 @@ module OasRails
|
|
15
24
|
@authenticate_all_routes_by_default = true
|
16
25
|
@security_schema = nil
|
17
26
|
@security_schemas = {}
|
27
|
+
@set_default_responses = true
|
28
|
+
@possible_default_responses = [:not_found, :unauthorized, :forbidden]
|
29
|
+
@response_body_of_default = { message: String }
|
18
30
|
end
|
19
31
|
|
20
32
|
def security_schema=(value)
|
@@ -24,15 +36,23 @@ module OasRails
|
|
24
36
|
end
|
25
37
|
|
26
38
|
def default_servers
|
27
|
-
[Server.new(url: "http://localhost:3000", description: "Rails Default Development Server")]
|
39
|
+
[Spec::Server.new(url: "http://localhost:3000", description: "Rails Default Development Server")]
|
28
40
|
end
|
29
41
|
|
30
42
|
def servers=(value)
|
31
|
-
@servers = value.map { |s| Server.new(url: s[:url], description: s[:description]) }
|
43
|
+
@servers = value.map { |s| Spec::Server.new(url: s[:url], description: s[:description]) }
|
32
44
|
end
|
33
45
|
|
34
46
|
def tags=(value)
|
35
|
-
@tags = value.map { |t| Tag.new(name: t[:name], description: t[:description]) }
|
47
|
+
@tags = value.map { |t| Spec::Tag.new(name: t[:name], description: t[:description]) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def excluded_columns_incoming
|
51
|
+
%i[id created_at updated_at deleted_at]
|
52
|
+
end
|
53
|
+
|
54
|
+
def excluded_columns_outgoing
|
55
|
+
[]
|
36
56
|
end
|
37
57
|
end
|
38
58
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module OasRails
|
2
|
+
module EsquemaBuilder
|
3
|
+
class << self
|
4
|
+
# Builds a schema for a class when it is used as incoming API data.
|
5
|
+
#
|
6
|
+
# @param klass [Class] The class for which the schema is built.
|
7
|
+
# @return [Hash] The schema as a JSON-compatible hash.
|
8
|
+
def build_incoming_schema(klass:)
|
9
|
+
configure_common_settings
|
10
|
+
Esquema.configuration.excluded_columns = OasRails.config.excluded_columns_incoming
|
11
|
+
|
12
|
+
Esquema::Builder.new(klass).build_schema.as_json
|
13
|
+
end
|
14
|
+
|
15
|
+
# Builds a schema for a class when it is used as outgoing API data.
|
16
|
+
#
|
17
|
+
# @param klass [Class] The class for which the schema is built.
|
18
|
+
# @return [Hash] The schema as a JSON-compatible hash.
|
19
|
+
def build_outgoing_schema(klass:)
|
20
|
+
configure_common_settings
|
21
|
+
Esquema.configuration.excluded_columns = OasRails.config.excluded_columns_outgoing
|
22
|
+
|
23
|
+
Esquema::Builder.new(klass).build_schema.as_json
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Configures common settings for schema building.
|
29
|
+
#
|
30
|
+
# Excludes associations and foreign keys from the schema.
|
31
|
+
def configure_common_settings
|
32
|
+
Esquema.configuration.exclude_associations = true
|
33
|
+
Esquema.configuration.exclude_foreign_keys = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Extractors
|
3
|
+
module OasRouteExtractor
|
4
|
+
def extract_summary(oas_route:)
|
5
|
+
oas_route.docstring.tags(:summary).first.try(:text) || generate_crud_name(oas_route.method, oas_route.controller.downcase) || "#{oas_route.verb} #{oas_route.path}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def extract_operation_id(oas_route:)
|
9
|
+
"#{oas_route.method}#{oas_route.path.gsub('/', '_').gsub(/[{}]/, '')}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def extract_tags(oas_route:)
|
13
|
+
tags = oas_route.docstring.tags(:tags).first
|
14
|
+
if tags.nil?
|
15
|
+
default_tags(oas_route:)
|
16
|
+
else
|
17
|
+
tags.text.split(",").map(&:strip).map(&:titleize)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_tags(oas_route:)
|
22
|
+
tags = []
|
23
|
+
if OasRails.config.default_tags_from == "namespace"
|
24
|
+
tag = oas_route.path.split('/').reject(&:empty?).first.try(:titleize)
|
25
|
+
tags << tag unless tag.nil?
|
26
|
+
else
|
27
|
+
tags << oas_route.controller.titleize
|
28
|
+
end
|
29
|
+
tags
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_security(oas_route:)
|
33
|
+
return [] if oas_route.docstring.tags(:no_auth).any?
|
34
|
+
|
35
|
+
if (methods = oas_route.docstring.tags(:auth).first)
|
36
|
+
OasRails.config.security_schemas.keys.map { |key| { key => [] } }.select do |schema|
|
37
|
+
methods.types.include?(schema.keys.first.to_s)
|
38
|
+
end
|
39
|
+
elsif OasRails.config.authenticate_all_routes_by_default
|
40
|
+
OasRails.config.security_schemas.keys.map { |key| { key => [] } }
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def generate_crud_name(method, controller)
|
49
|
+
controller_name = controller.to_s.underscore.humanize.downcase.pluralize
|
50
|
+
|
51
|
+
case method.to_sym
|
52
|
+
when :index
|
53
|
+
"List #{controller_name}"
|
54
|
+
when :show
|
55
|
+
"View #{controller_name.singularize}"
|
56
|
+
when :create
|
57
|
+
"Create new #{controller_name.singularize}"
|
58
|
+
when :update
|
59
|
+
"Update #{controller_name.singularize}"
|
60
|
+
when :destroy
|
61
|
+
"Delete #{controller_name.singularize}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|