explicit 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -1
- data/app/views/explicit/documentation/_page.html.erb +2 -1
- data/app/views/explicit/documentation/type/_float.html.erb +25 -0
- data/config/locales/en.yml +7 -4
- data/lib/explicit/documentation/output/swagger.rb +40 -11
- data/lib/explicit/request.rb +33 -6
- data/lib/explicit/type/date.rb +4 -4
- data/lib/explicit/type/float.rb +87 -0
- data/lib/explicit/type/integer.rb +13 -5
- data/lib/explicit/type/one_of.rb +14 -7
- data/lib/explicit/type.rb +19 -3
- data/lib/explicit/version.rb +1 -1
- data/lib/explicit.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd88a349ccfac424582d31d9d4f325f5ff03ede07eee06204938643b836310a5
|
4
|
+
data.tar.gz: 31c41a8b16b54c1d3e337cc7fb1458af43d24a97123e5f9d68470daf7b90c6dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c58b39e3709dbc6edba831aa1c746eb919c0c059ca2c386ac9840ff7ed101b9b0b7342e1e6885b368c3456e23b17e31fc54c8608b2d33efeacdfc3d41895ef55
|
7
|
+
data.tar.gz: 8e6b2055a6c55db8192a9ff5fd60773bfad06d1acc136b5056eb037ae3b76593f1d6b594c44c3c7ac63c13bb7f1a2d38a37c09cd670b40c0dd50c775595e0015
|
data/README.md
CHANGED
@@ -28,6 +28,7 @@ documented types at runtime.
|
|
28
28
|
- [Description](#description)
|
29
29
|
- [Enum](#enum)
|
30
30
|
- [File](#file)
|
31
|
+
- [Float](#float)
|
31
32
|
- [Hash](#hash)
|
32
33
|
- [Integer](#integer)
|
33
34
|
- [Literal](#literal)
|
@@ -141,6 +142,9 @@ request instead of `Explicit::Request`. For example:
|
|
141
142
|
|
142
143
|
```ruby
|
143
144
|
AuthenticatedRequest = Explicit::Request.new do
|
145
|
+
base_url "https://my-app.com"
|
146
|
+
base_path "/api/v1"
|
147
|
+
|
144
148
|
header "Authorization", [:string, format: /Bearer [a-zA-Z0-9]{20}/]
|
145
149
|
|
146
150
|
response 403, { error: "unauthorized" }
|
@@ -550,6 +554,18 @@ match value_type. If you are expecting a hash with a specific set of keys use a
|
|
550
554
|
|
551
555
|
Value must be an uploaded file using "multipart/form-data" encoding.
|
552
556
|
|
557
|
+
### Float
|
558
|
+
|
559
|
+
```ruby
|
560
|
+
:float
|
561
|
+
[:float, negative: false]
|
562
|
+
[:float, positive: false]
|
563
|
+
[:float, min: 0] # inclusive
|
564
|
+
[:float, max: 10] # inclusive
|
565
|
+
```
|
566
|
+
|
567
|
+
Float encoded string alues such as "0.5" or "500.01" are automatically converted to `Float`.
|
568
|
+
|
553
569
|
### Integer
|
554
570
|
|
555
571
|
```ruby
|
@@ -561,7 +577,7 @@ Value must be an uploaded file using "multipart/form-data" encoding.
|
|
561
577
|
```
|
562
578
|
|
563
579
|
Integer encoded string values such as "10" or "-2" are automatically converted
|
564
|
-
to
|
580
|
+
to `Integer`.
|
565
581
|
|
566
582
|
### Literal
|
567
583
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
<html>
|
3
3
|
<head>
|
4
4
|
<title><%= page_title || "API Documentation" %></title>
|
5
|
+
<meta charset="UTF-8">
|
5
6
|
|
6
7
|
<% if favicon_url %>
|
7
8
|
<link rel="icon" href="<%= favicon_url %>" />
|
@@ -50,7 +51,7 @@
|
|
50
51
|
Version <%= version %>
|
51
52
|
</div>
|
52
53
|
<div class="p-1 w-1/2">
|
53
|
-
<%= link_to url_helpers.
|
54
|
+
<%= link_to "https://petstore.swagger.io/?url=#{url_helpers.explicit_documentation_swagger_url(host: request.host)}", target: "_blank", class: "flex items-center justify-center gap-1 text-neutral-900" do %>
|
54
55
|
<span>Swagger</span>
|
55
56
|
|
56
57
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4">
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%= type_constraints do %>
|
2
|
+
<% if type.min.present? %>
|
3
|
+
<%= type_constraint "min", type.min %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<% if type.max.present? %>
|
7
|
+
<%= type_constraint "max", type.max %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if type.negative == false %>
|
11
|
+
<%= type_constraint "not", "negative" %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% if type.negative == true %>
|
15
|
+
<%= type_constraint "only", "negative" %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if type.positive == false %>
|
19
|
+
<%= type_constraint "not", "positive" %>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% if type.positive == true %>
|
23
|
+
<%= type_constraint "only", "positive" %>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
data/config/locales/en.yml
CHANGED
@@ -34,11 +34,14 @@ en:
|
|
34
34
|
file: "must be a file"
|
35
35
|
file_max_size: "must be smaller than %{max_size}"
|
36
36
|
file_content_type: "file content type must be one of: %{allowed_content_types}"
|
37
|
+
float: "must be a number"
|
37
38
|
integer: "must be an integer"
|
38
39
|
min: "must be at least %{min}"
|
39
40
|
max: "must be at most %{max}"
|
40
41
|
not_negative: "must not be negative"
|
42
|
+
only_negative: "must be negative"
|
41
43
|
not_positive: "must not be positive"
|
44
|
+
only_positive: "must be positive"
|
42
45
|
literal: "must be %{value}"
|
43
46
|
one_of_separator: "OR"
|
44
47
|
string: "must be a string"
|
@@ -61,9 +64,9 @@ en:
|
|
61
64
|
file_max_size: "* Max size: %{max_size}"
|
62
65
|
file_content_types: "* Content types: %{content_types}"
|
63
66
|
hash_not_empty: "* Must have at least one value"
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
67
|
+
number_not_positive: "* Must not be positive"
|
68
|
+
number_only_positive: "* Must be positive"
|
69
|
+
number_not_negative: "* Must not be negative"
|
70
|
+
number_only_negative: "* Must be negative"
|
68
71
|
string_not_empty: "* Must not be empty"
|
69
72
|
string_downcase: "* Case insensitive"
|
@@ -12,6 +12,20 @@ module Explicit::Documentation::Output
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def swagger_document
|
15
|
+
paths = build_paths_from_requests
|
16
|
+
|
17
|
+
securitySchemes = {}.tap do |hash|
|
18
|
+
requests = paths.flat_map { |path, methods| methods.values }
|
19
|
+
|
20
|
+
if requests.filter { _1.dig(:security, 0, :basicAuth) }.any?
|
21
|
+
hash[:basicAuth] = { type: "http", scheme: "basic" }
|
22
|
+
end
|
23
|
+
|
24
|
+
if requests.filter { _1.dig(:security, 0, :bearerAuth) }.any?
|
25
|
+
hash[:bearerAuth] = { type: "http", scheme: "bearer" }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
15
29
|
{
|
16
30
|
openapi: "3.0.1",
|
17
31
|
info: {
|
@@ -24,14 +38,15 @@ module Explicit::Documentation::Output
|
|
24
38
|
}
|
25
39
|
],
|
26
40
|
tags: build_tags_from_sections,
|
27
|
-
paths: build_paths_from_requests
|
41
|
+
paths: build_paths_from_requests,
|
42
|
+
components: { securitySchemes: }
|
28
43
|
}
|
29
44
|
end
|
30
45
|
|
31
46
|
def call(request)
|
32
47
|
@swagger_document ||= swagger_document
|
33
48
|
|
34
|
-
[200, {"Content-Type" => "application/json"}, [@swagger_document.to_json]]
|
49
|
+
[ 200, { "Content-Type" => "application/json" }, [ @swagger_document.to_json ] ]
|
35
50
|
end
|
36
51
|
|
37
52
|
def inspect
|
@@ -43,7 +58,7 @@ module Explicit::Documentation::Output
|
|
43
58
|
base_urls = builder.requests.map(&:get_base_url).uniq
|
44
59
|
base_paths = builder.requests.map(&:get_base_path).uniq
|
45
60
|
|
46
|
-
if !base_urls.one?
|
61
|
+
if !base_urls.compact_blank.empty? && !base_urls.one?
|
47
62
|
raise InconsistentBaseURLError.new <<~TXT
|
48
63
|
There are requests with different base URLs in the same documentation,
|
49
64
|
which is not supported by Swagger.
|
@@ -56,7 +71,7 @@ module Explicit::Documentation::Output
|
|
56
71
|
TXT
|
57
72
|
end
|
58
73
|
|
59
|
-
if !base_paths.one?
|
74
|
+
if !base_paths.compact_blank.empty? && !base_paths.one?
|
60
75
|
raise InconsistentBasePathError.new <<~TXT
|
61
76
|
There are requests with different base paths in the same documentation,
|
62
77
|
which is not supported by Swagger.
|
@@ -69,7 +84,7 @@ module Explicit::Documentation::Output
|
|
69
84
|
TXT
|
70
85
|
end
|
71
86
|
|
72
|
-
base_urls.first + base_paths.first
|
87
|
+
(base_urls.first || "") + (base_paths.first || "")
|
73
88
|
end
|
74
89
|
|
75
90
|
def build_tags_from_sections
|
@@ -86,13 +101,23 @@ module Explicit::Documentation::Output
|
|
86
101
|
request = page.request
|
87
102
|
route = request.routes.first
|
88
103
|
|
104
|
+
security =
|
105
|
+
if request.requires_basic_authorization?
|
106
|
+
[ { basicAuth: [] } ]
|
107
|
+
elsif request.requires_bearer_authorization?
|
108
|
+
[ { bearerAuth: [] } ]
|
109
|
+
else
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
|
89
113
|
paths[route.path_with_curly_syntax][route.method.to_s] = {
|
90
|
-
tags: [section.name],
|
114
|
+
tags: [ section.name ],
|
91
115
|
summary: request.get_title,
|
92
116
|
description: request.get_description,
|
93
117
|
parameters: build_parameters(request),
|
94
118
|
requestBody: build_request_body(request),
|
95
|
-
responses: build_responses(request)
|
119
|
+
responses: build_responses(request),
|
120
|
+
security:
|
96
121
|
}.compact_blank
|
97
122
|
end
|
98
123
|
end
|
@@ -102,7 +127,11 @@ module Explicit::Documentation::Output
|
|
102
127
|
|
103
128
|
def build_parameters(request)
|
104
129
|
headers =
|
105
|
-
request.headers_type.attributes.
|
130
|
+
request.headers_type.attributes.filter_map do |name, type|
|
131
|
+
# NOTE: skip Authorization header because swagger prefers the `security` directive for basic and bearer
|
132
|
+
# authorization schemas. If not basic or bearer, then we add the Authorization header.
|
133
|
+
next if name == "Authorization" && !request.custom_authorization_format?
|
134
|
+
|
106
135
|
{
|
107
136
|
name: name.to_s,
|
108
137
|
in: "header",
|
@@ -132,7 +161,7 @@ module Explicit::Documentation::Output
|
|
132
161
|
|
133
162
|
return nil if body_params_type.attributes.empty?
|
134
163
|
|
135
|
-
examples =
|
164
|
+
examples =
|
136
165
|
request.examples
|
137
166
|
.flat_map { |_, examples| examples }
|
138
167
|
.filter_map do |example|
|
@@ -141,7 +170,7 @@ module Explicit::Documentation::Output
|
|
141
170
|
in [:error, _] then nil
|
142
171
|
end
|
143
172
|
end
|
144
|
-
.map.with_index { |example, index| [index, { value: example }] }
|
173
|
+
.map.with_index { |example, index| [ index, { value: example } ] }
|
145
174
|
.to_h
|
146
175
|
|
147
176
|
{
|
@@ -160,7 +189,7 @@ module Explicit::Documentation::Output
|
|
160
189
|
|
161
190
|
request.responses.each do |status, _|
|
162
191
|
examples = request.examples[status].map.with_index do |example, index|
|
163
|
-
[index.to_s, { value: example.response.data }]
|
192
|
+
[ index.to_s, { value: example.response.data } ]
|
164
193
|
end.to_h
|
165
194
|
|
166
195
|
responses[status] = {
|
data/lib/explicit/request.rb
CHANGED
@@ -12,13 +12,15 @@ class Explicit::Request
|
|
12
12
|
|
13
13
|
instance_eval(&block)
|
14
14
|
|
15
|
+
define_missing_path_params!
|
16
|
+
|
15
17
|
if Explicit.configuration.rescue_from_invalid_params? && @params.any?
|
16
18
|
@responses[422] << {
|
17
19
|
error: "invalid_params",
|
18
20
|
params: [
|
19
21
|
:description,
|
20
22
|
"An object containing error messages for all invalid params",
|
21
|
-
[:hash, :string, :string]
|
23
|
+
[ :hash, :string, :string ]
|
22
24
|
]
|
23
25
|
}
|
24
26
|
end
|
@@ -76,19 +78,19 @@ class Explicit::Request
|
|
76
78
|
raise ArgumentError("duplicated param #{name}") if @params.key?(name)
|
77
79
|
|
78
80
|
if options[:optional]
|
79
|
-
type = [:nilable, type]
|
81
|
+
type = [ :nilable, type ]
|
80
82
|
end
|
81
83
|
|
82
84
|
if (defaultval = options[:default])
|
83
|
-
type = [:default, defaultval, type]
|
85
|
+
type = [ :default, defaultval, type ]
|
84
86
|
end
|
85
87
|
|
86
88
|
if (description = options[:description])
|
87
|
-
type = [:description, description, type]
|
89
|
+
type = [ :description, description, type ]
|
88
90
|
end
|
89
91
|
|
90
92
|
if @routes.first&.params&.include?(name)
|
91
|
-
type = [:_param_location, :path, type]
|
93
|
+
type = [ :_param_location, :path, type ]
|
92
94
|
end
|
93
95
|
|
94
96
|
@params[name] = type
|
@@ -140,6 +142,31 @@ class Explicit::Request
|
|
140
142
|
end
|
141
143
|
|
142
144
|
def responses_type(status:)
|
143
|
-
Explicit::Type.build([:one_of, *@responses[status]])
|
145
|
+
Explicit::Type.build([ :one_of, *@responses[status] ])
|
146
|
+
end
|
147
|
+
|
148
|
+
def custom_authorization_format?
|
149
|
+
@headers.key?("Authorization") && !requires_basic_authorization? && !requires_bearer_authorization?
|
150
|
+
end
|
151
|
+
|
152
|
+
def requires_basic_authorization?
|
153
|
+
authorization = headers_type.attributes["Authorization"]
|
154
|
+
|
155
|
+
authorization&.format&.to_s&.include?("Basic")
|
144
156
|
end
|
157
|
+
|
158
|
+
def requires_bearer_authorization?
|
159
|
+
authorization = headers_type.attributes["Authorization"]
|
160
|
+
|
161
|
+
authorization&.format&.to_s&.include?("Bearer")
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
def define_missing_path_params!
|
166
|
+
@routes.first&.params&.each do |path_param_name|
|
167
|
+
if @params[path_param_name.to_sym].blank?
|
168
|
+
param(path_param_name.to_sym, :string)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
145
172
|
end
|
data/lib/explicit/type/date.rb
CHANGED
@@ -11,7 +11,7 @@ class Explicit::Type::Date < Explicit::Type
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def validate(value)
|
14
|
-
return [:ok, value] if value.is_a?(::Date)
|
14
|
+
return [ :ok, value ] if value.is_a?(::Date)
|
15
15
|
return error_i18n("string") if !value.is_a?(::String)
|
16
16
|
|
17
17
|
date = ::Date.parse(value, false)
|
@@ -32,7 +32,7 @@ class Explicit::Type::Date < Explicit::Type
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
[:ok, date]
|
35
|
+
[ :ok, date ]
|
36
36
|
rescue ::Date::Error
|
37
37
|
error_i18n("date_format")
|
38
38
|
end
|
@@ -53,14 +53,14 @@ class Explicit::Type::Date < Explicit::Type
|
|
53
53
|
|
54
54
|
concerning :Swagger do
|
55
55
|
def swagger_schema
|
56
|
-
{
|
56
|
+
merge_base_swagger_schema({
|
57
57
|
type: "string",
|
58
58
|
pattern: /\d{4}-\d{2}-\d{2}/.inspect[1..-2],
|
59
59
|
format: "date",
|
60
60
|
description_topics: [
|
61
61
|
swagger_i18n("date_format")
|
62
62
|
]
|
63
|
-
}
|
63
|
+
})
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Explicit::Type::Float < Explicit::Type
|
4
|
+
attr_reader :min, :max, :negative, :positive
|
5
|
+
|
6
|
+
def initialize(min: nil, max: nil, negative: nil, positive: nil)
|
7
|
+
@min = min
|
8
|
+
@max = max
|
9
|
+
@negative = negative
|
10
|
+
@positive = positive
|
11
|
+
end
|
12
|
+
|
13
|
+
ParseFromString = ->(value) do
|
14
|
+
Float(value)
|
15
|
+
rescue ::ArgumentError
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate(value)
|
20
|
+
value =
|
21
|
+
if value.is_a?(::Integer) || value.is_a?(::Float) || value.is_a?(::BigDecimal)
|
22
|
+
value
|
23
|
+
elsif value.is_a?(::String)
|
24
|
+
ParseFromString[value]
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
return error_i18n("float") if value.nil?
|
30
|
+
|
31
|
+
if min && value < min
|
32
|
+
return error_i18n("min", min:)
|
33
|
+
end
|
34
|
+
|
35
|
+
if max && value > max
|
36
|
+
return error_i18n("max", max:)
|
37
|
+
end
|
38
|
+
|
39
|
+
if negative == false && value < 0
|
40
|
+
return error_i18n("not_negative")
|
41
|
+
end
|
42
|
+
|
43
|
+
if negative == true && value >= 0
|
44
|
+
return error_i18n("only_negative")
|
45
|
+
end
|
46
|
+
|
47
|
+
if positive == false && value > 0
|
48
|
+
return error_i18n("not_positive")
|
49
|
+
end
|
50
|
+
|
51
|
+
if positive == true && value <= 0
|
52
|
+
return error_i18n("only_positive")
|
53
|
+
end
|
54
|
+
|
55
|
+
[ :ok, value ]
|
56
|
+
end
|
57
|
+
|
58
|
+
concerning :Webpage do
|
59
|
+
def summary
|
60
|
+
"float"
|
61
|
+
end
|
62
|
+
|
63
|
+
def partial
|
64
|
+
"explicit/documentation/type/float"
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_details?
|
68
|
+
min.present? || max.present? || !negative.nil? || !positive.nil?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
concerning :Swagger do
|
73
|
+
def swagger_schema
|
74
|
+
merge_base_swagger_schema({
|
75
|
+
type: "number",
|
76
|
+
minimum: min,
|
77
|
+
maximum: max,
|
78
|
+
description_topics: [
|
79
|
+
positive == false ? swagger_i18n("number_not_positive") : nil,
|
80
|
+
positive == true ? swagger_i18n("number_only_positive") : nil,
|
81
|
+
negative == false ? swagger_i18n("number_not_negative") : nil,
|
82
|
+
negative == true ? swagger_i18n("number_only_negative") : nil
|
83
|
+
]
|
84
|
+
})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -40,11 +40,19 @@ class Explicit::Type::Integer < Explicit::Type
|
|
40
40
|
return error_i18n("not_negative")
|
41
41
|
end
|
42
42
|
|
43
|
+
if negative == true && value >= 0
|
44
|
+
return error_i18n("only_negative")
|
45
|
+
end
|
46
|
+
|
43
47
|
if positive == false && value > 0
|
44
48
|
return error_i18n("not_positive")
|
45
49
|
end
|
46
50
|
|
47
|
-
|
51
|
+
if positive == true && value <= 0
|
52
|
+
return error_i18n("only_positive")
|
53
|
+
end
|
54
|
+
|
55
|
+
[ :ok, value ]
|
48
56
|
end
|
49
57
|
|
50
58
|
concerning :Webpage do
|
@@ -68,10 +76,10 @@ class Explicit::Type::Integer < Explicit::Type
|
|
68
76
|
minimum: min,
|
69
77
|
maximum: max,
|
70
78
|
description_topics: [
|
71
|
-
positive == false ? swagger_i18n("
|
72
|
-
positive == true ? swagger_i18n("
|
73
|
-
negative == false ? swagger_i18n("
|
74
|
-
negative == true ? swagger_i18n("
|
79
|
+
positive == false ? swagger_i18n("number_not_positive") : nil,
|
80
|
+
positive == true ? swagger_i18n("number_only_positive") : nil,
|
81
|
+
negative == false ? swagger_i18n("number_not_negative") : nil,
|
82
|
+
negative == true ? swagger_i18n("number_only_negative") : nil
|
75
83
|
]
|
76
84
|
})
|
77
85
|
end
|
data/lib/explicit/type/one_of.rb
CHANGED
@@ -27,28 +27,35 @@ class Explicit::Type::OneOf < Explicit::Type
|
|
27
27
|
@subtypes.each do |subtype|
|
28
28
|
case subtype.validate(value)
|
29
29
|
in [:ok, validated_value]
|
30
|
-
return [:ok, validated_value]
|
30
|
+
return [ :ok, validated_value ]
|
31
31
|
in [:error, err]
|
32
32
|
errors << err
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
if (err = guess_error_for_intended_subtype_via_matching_literal(value:, errors:))
|
37
|
-
return [:error, err]
|
37
|
+
return [ :error, err ]
|
38
38
|
end
|
39
39
|
|
40
40
|
if (err = guess_error_for_intended_subtype_via_matching_keys(value:, errors:))
|
41
|
-
return [:error, err]
|
41
|
+
return [ :error, err ]
|
42
42
|
end
|
43
43
|
|
44
|
+
separator =
|
45
|
+
if ::I18n.exists?("explicit.errors.one_of_separator")
|
46
|
+
::I18n.t("explicit.errors.one_of_separator")
|
47
|
+
else
|
48
|
+
::I18n.t("explicit.errors.one_of_separator", locale: :en)
|
49
|
+
end
|
50
|
+
|
44
51
|
error =
|
45
52
|
if @subtypes_are_records
|
46
|
-
errors.map { ::JSON.pretty_generate(_1) }.join("\n\n#{
|
53
|
+
errors.map { ::JSON.pretty_generate(_1) }.join("\n\n#{separator}\n\n")
|
47
54
|
else
|
48
|
-
errors.join(" #{
|
55
|
+
errors.join(" #{separator} ")
|
49
56
|
end
|
50
57
|
|
51
|
-
[:error, error]
|
58
|
+
[ :error, error ]
|
52
59
|
end
|
53
60
|
|
54
61
|
def guess_error_for_intended_subtype_via_matching_literal(value:, errors:)
|
@@ -101,4 +108,4 @@ class Explicit::Type::OneOf < Explicit::Type
|
|
101
108
|
{ oneOf: subtypes.map(&:swagger_schema) }
|
102
109
|
end
|
103
110
|
end
|
104
|
-
end
|
111
|
+
end
|
data/lib/explicit/type.rb
CHANGED
@@ -59,6 +59,11 @@ class Explicit::Type
|
|
59
59
|
in [:file, options]
|
60
60
|
Explicit::Type::File.new(**options)
|
61
61
|
|
62
|
+
in :float
|
63
|
+
Explicit::Type::Float.new
|
64
|
+
in [:float, options]
|
65
|
+
Explicit::Type::Float.new(**options)
|
66
|
+
|
62
67
|
in :integer
|
63
68
|
Explicit::Type::Integer.new
|
64
69
|
in [:integer, options]
|
@@ -109,13 +114,24 @@ class Explicit::Type
|
|
109
114
|
def error_i18n(name, context = {})
|
110
115
|
key = "explicit.errors.#{name}"
|
111
116
|
|
112
|
-
|
117
|
+
translation =
|
118
|
+
if ::I18n.exists?(key)
|
119
|
+
::I18n.t(key, **context)
|
120
|
+
else
|
121
|
+
::I18n.t(key, **context.merge(locale: :en))
|
122
|
+
end
|
123
|
+
|
124
|
+
[ :error, translation ]
|
113
125
|
end
|
114
126
|
|
115
127
|
def swagger_i18n(name, context = {})
|
116
128
|
key = "explicit.swagger.#{name}"
|
117
129
|
|
118
|
-
::I18n.
|
130
|
+
if ::I18n.exists?(key)
|
131
|
+
::I18n.t(key, **context)
|
132
|
+
else
|
133
|
+
::I18n.t(key, **context.merge(locale: :en))
|
134
|
+
end
|
119
135
|
end
|
120
136
|
|
121
137
|
def merge_base_swagger_schema(attributes)
|
@@ -144,4 +160,4 @@ class Explicit::Type
|
|
144
160
|
|
145
161
|
base_attributes.merge(attributes).compact_blank
|
146
162
|
end
|
147
|
-
end
|
163
|
+
end
|
data/lib/explicit/version.rb
CHANGED
data/lib/explicit.rb
CHANGED
@@ -35,6 +35,7 @@ require "explicit/type/date_time_unix_epoch"
|
|
35
35
|
require "explicit/type/date"
|
36
36
|
require "explicit/type/enum"
|
37
37
|
require "explicit/type/file"
|
38
|
+
require "explicit/type/float"
|
38
39
|
require "explicit/type/hash"
|
39
40
|
require "explicit/type/integer"
|
40
41
|
require "explicit/type/literal"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: explicit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luiz Vasconcellos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- app/views/explicit/documentation/type/_date_time_unix_epoch.html.erb
|
67
67
|
- app/views/explicit/documentation/type/_enum.html.erb
|
68
68
|
- app/views/explicit/documentation/type/_file.html.erb
|
69
|
+
- app/views/explicit/documentation/type/_float.html.erb
|
69
70
|
- app/views/explicit/documentation/type/_hash.html.erb
|
70
71
|
- app/views/explicit/documentation/type/_integer.html.erb
|
71
72
|
- app/views/explicit/documentation/type/_one_of.html.erb
|
@@ -104,6 +105,7 @@ files:
|
|
104
105
|
- lib/explicit/type/date_time_unix_epoch.rb
|
105
106
|
- lib/explicit/type/enum.rb
|
106
107
|
- lib/explicit/type/file.rb
|
108
|
+
- lib/explicit/type/float.rb
|
107
109
|
- lib/explicit/type/hash.rb
|
108
110
|
- lib/explicit/type/integer.rb
|
109
111
|
- lib/explicit/type/literal.rb
|