apipie-rails 0.9.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -14
- data/.rubocop_todo.yml +102 -213
- data/CHANGELOG.md +17 -6
- data/README.rst +12 -12
- data/app/controllers/apipie/apipies_controller.rb +4 -4
- data/lib/apipie/apipie_module.rb +4 -4
- data/lib/apipie/application.rb +70 -54
- data/lib/apipie/configuration.rb +19 -26
- data/lib/apipie/dsl_definition.rb +4 -5
- data/lib/apipie/extractor/collector.rb +2 -2
- data/lib/apipie/extractor.rb +1 -1
- data/lib/apipie/generator/config.rb +12 -0
- data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
- data/lib/apipie/generator/swagger/config.rb +78 -0
- data/lib/apipie/generator/swagger/context.rb +12 -1
- data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
- data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +86 -0
- data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
- data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
- data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
- data/lib/apipie/generator/swagger/method_description/response_service.rb +58 -0
- data/lib/apipie/generator/swagger/method_description.rb +2 -0
- data/lib/apipie/generator/swagger/operation_id.rb +1 -1
- data/lib/apipie/generator/swagger/param_description/builder.rb +4 -4
- data/lib/apipie/generator/swagger/param_description/composite.rb +9 -1
- data/lib/apipie/generator/swagger/param_description/in.rb +1 -1
- data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
- data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
- data/lib/apipie/generator/swagger/param_description/type.rb +9 -2
- data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
- data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
- data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
- data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
- data/lib/apipie/generator/swagger/schema.rb +63 -0
- data/lib/apipie/generator/swagger/type_extractor.rb +0 -19
- data/lib/apipie/generator/swagger/warning.rb +3 -6
- data/lib/apipie/generator/swagger/warning_writer.rb +7 -1
- data/lib/apipie/method_description.rb +4 -2
- data/lib/apipie/param_description.rb +4 -2
- data/lib/apipie/resource_description.rb +1 -1
- data/lib/apipie/swagger_generator.rb +27 -551
- data/lib/apipie/validator.rb +7 -3
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +17 -0
- data/lib/tasks/apipie.rake +15 -10
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +2 -2
- data/spec/controllers/pets_controller_spec.rb +10 -16
- data/spec/controllers/users_controller_spec.rb +2 -2
- data/spec/dummy/app/controllers/pets_controller.rb +4 -4
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +2 -2
- data/spec/dummy/app/controllers/twitter_example_controller.rb +2 -2
- data/spec/dummy/app/controllers/users_controller.rb +5 -5
- data/spec/lib/apipie/application_spec.rb +16 -7
- data/spec/lib/apipie/configuration_spec.rb +15 -0
- data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
- data/spec/lib/apipie/generator/swagger/context_spec.rb +22 -2
- data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +106 -0
- data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
- data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +1 -1
- data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +2 -2
- data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +7 -7
- data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
- data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
- data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
- data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
- data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +0 -43
- data/spec/lib/apipie/generator/swagger/warning_spec.rb +1 -1
- data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +19 -7
- data/spec/lib/apipie/method_description_spec.rb +101 -66
- data/spec/lib/apipie/param_description_spec.rb +209 -49
- data/spec/lib/apipie/param_group_spec.rb +1 -0
- data/spec/lib/apipie/resource_description_spec.rb +1 -1
- data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
- data/spec/lib/apipie/validator_spec.rb +47 -11
- data/spec/lib/swagger/rake_swagger_spec.rb +4 -4
- data/spec/lib/swagger/swagger_dsl_spec.rb +7 -7
- data/spec/lib/validators/array_validator_spec.rb +1 -1
- metadata +28 -2
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Apipie
|
4
|
+
module Generator
|
5
|
+
module Swagger
|
6
|
+
class Config
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
CONFIG_ATTRIBUTES = [:include_warning_tags, :content_type_input,
|
10
|
+
:json_input_uses_refs, :suppress_warnings, :api_host,
|
11
|
+
:generate_x_computed_id_field, :allow_additional_properties_in_response,
|
12
|
+
:responses_use_refs, :schemes, :security_definitions,
|
13
|
+
:global_security].freeze
|
14
|
+
|
15
|
+
attr_accessor(*CONFIG_ATTRIBUTES)
|
16
|
+
|
17
|
+
CONFIG_ATTRIBUTES.each do |attribute|
|
18
|
+
old_setter_method = "swagger_#{attribute}="
|
19
|
+
define_method(old_setter_method) do |value|
|
20
|
+
ActiveSupport::Deprecation.warn(
|
21
|
+
<<~HEREDOC
|
22
|
+
config.#{old_setter_method}#{value} is deprecated.
|
23
|
+
config.generator.swagger.#{attribute} instead.
|
24
|
+
HEREDOC
|
25
|
+
)
|
26
|
+
|
27
|
+
send("#{attribute}=", value)
|
28
|
+
end
|
29
|
+
|
30
|
+
old_setter_method = "swagger_#{attribute}"
|
31
|
+
define_method(old_setter_method) do
|
32
|
+
ActiveSupport::Deprecation.warn(
|
33
|
+
<<~HEREDOC
|
34
|
+
config.#{old_setter_method} is deprecated.
|
35
|
+
Use config.generator.swagger.#{attribute} instead.
|
36
|
+
HEREDOC
|
37
|
+
)
|
38
|
+
|
39
|
+
send(attribute)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
alias include_warning_tags? include_warning_tags
|
44
|
+
alias json_input_uses_refs? json_input_uses_refs
|
45
|
+
alias responses_use_refs? responses_use_refs
|
46
|
+
alias generate_x_computed_id_field? generate_x_computed_id_field
|
47
|
+
alias swagger_include_warning_tags? swagger_include_warning_tags
|
48
|
+
alias swagger_json_input_uses_refs? swagger_json_input_uses_refs
|
49
|
+
alias swagger_responses_use_refs? swagger_responses_use_refs
|
50
|
+
alias swagger_generate_x_computed_id_field? swagger_generate_x_computed_id_field
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@content_type_input = :form_data # this can be :json or :form_data
|
54
|
+
@json_input_uses_refs = false
|
55
|
+
@include_warning_tags = false
|
56
|
+
@suppress_warnings = false # [105,100,102]
|
57
|
+
@api_host = 'localhost:3000'
|
58
|
+
@generate_x_computed_id_field = false
|
59
|
+
@allow_additional_properties_in_response = false
|
60
|
+
@responses_use_refs = true
|
61
|
+
@schemes = [:https]
|
62
|
+
@security_definitions = {}
|
63
|
+
@global_security = []
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.deprecated_methods
|
67
|
+
CONFIG_ATTRIBUTES.map do |attribute|
|
68
|
+
[
|
69
|
+
:"swagger_#{attribute}=",
|
70
|
+
:"swagger_#{attribute}?",
|
71
|
+
:"swagger_#{attribute}"
|
72
|
+
]
|
73
|
+
end.flatten
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class Apipie::Generator::Swagger::Context
|
2
|
-
attr_reader :default_in_value, :language, :http_method, :controller_method
|
2
|
+
attr_reader :default_in_value, :language, :http_method, :controller_method,
|
3
|
+
:prefix
|
3
4
|
|
4
5
|
def initialize(
|
5
6
|
allow_null:,
|
6
7
|
http_method:,
|
7
8
|
controller_method:,
|
9
|
+
prefix: nil,
|
8
10
|
default_in_value: nil,
|
9
11
|
language: nil,
|
10
12
|
in_schema: true
|
@@ -15,6 +17,7 @@ class Apipie::Generator::Swagger::Context
|
|
15
17
|
@in_schema = in_schema
|
16
18
|
@http_method = http_method
|
17
19
|
@controller_method = controller_method
|
20
|
+
@prefix = prefix
|
18
21
|
end
|
19
22
|
|
20
23
|
def allow_null?
|
@@ -24,4 +27,12 @@ class Apipie::Generator::Swagger::Context
|
|
24
27
|
def in_schema?
|
25
28
|
@in_schema == true
|
26
29
|
end
|
30
|
+
|
31
|
+
def add_to_prefix!(prefix)
|
32
|
+
@prefix = if @prefix.present?
|
33
|
+
"#{@prefix}[#{prefix}]"
|
34
|
+
else
|
35
|
+
prefix
|
36
|
+
end
|
37
|
+
end
|
27
38
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::ApiDecorator < SimpleDelegator
|
2
|
+
def normalized_http_method
|
3
|
+
@normalized_http_method ||= http_method.downcase
|
4
|
+
end
|
5
|
+
|
6
|
+
def summary(method_description:, language:)
|
7
|
+
s = Apipie.app.translate(short_description, language)
|
8
|
+
|
9
|
+
if s.blank?
|
10
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
11
|
+
Apipie::Generator::Swagger::Warning::MISSING_METHOD_SUMMARY_CODE,
|
12
|
+
method_description.ruby_name
|
13
|
+
).warn_through_writer
|
14
|
+
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::ApiSchemaService
|
2
|
+
# @param [Apipie::Generator::Swagger::MethodDescription::Decorator] method_description
|
3
|
+
def initialize(method_description, language: nil)
|
4
|
+
@method_description = method_description
|
5
|
+
@language = language
|
6
|
+
end
|
7
|
+
|
8
|
+
# @return [Hash]
|
9
|
+
def call
|
10
|
+
@method_description.apis.each_with_object({}) do |api, paths|
|
11
|
+
api = Apipie::Generator::Swagger::MethodDescription::ApiDecorator.new(api)
|
12
|
+
path = Apipie::Generator::Swagger::PathDecorator.new(api.path)
|
13
|
+
op_id = Apipie::Generator::Swagger::OperationId.from(api).to_s
|
14
|
+
|
15
|
+
if Apipie.configuration.generator.swagger.generate_x_computed_id_field?
|
16
|
+
Apipie::Generator::Swagger::ComputedInterfaceId.instance.add!(op_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
parameters = Apipie::Generator::Swagger::MethodDescription::ParametersService
|
20
|
+
.new(@method_description, path: path, http_method: api.normalized_http_method)
|
21
|
+
.call
|
22
|
+
|
23
|
+
paths[path.swagger_path(@method_description)] ||= {}
|
24
|
+
paths[path.swagger_path(@method_description)][api.normalized_http_method] = {
|
25
|
+
tags: tags,
|
26
|
+
consumes: consumes,
|
27
|
+
operationId: op_id,
|
28
|
+
summary: api.summary(method_description: @method_description, language: @language),
|
29
|
+
parameters: parameters,
|
30
|
+
responses: responses(api),
|
31
|
+
description: Apipie.app.translate(@method_description.full_description, @language)
|
32
|
+
}.compact
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def summary(api)
|
39
|
+
translated_description = Apipie.app.translate(api.short_description, @language)
|
40
|
+
|
41
|
+
return translated_description if translated_description.present?
|
42
|
+
|
43
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
44
|
+
Apipie::Generator::Swagger::Warning::MISSING_METHOD_SUMMARY_CODE,
|
45
|
+
@method_description.ruby_name
|
46
|
+
).warn_through_writer
|
47
|
+
end
|
48
|
+
|
49
|
+
def tags
|
50
|
+
[@method_description.resource._id] +
|
51
|
+
warning_tags +
|
52
|
+
@method_description.tag_list.tags
|
53
|
+
end
|
54
|
+
|
55
|
+
def warning_tags
|
56
|
+
if Apipie.configuration.generator.swagger.include_warning_tags? &&
|
57
|
+
Apipie::Generator::Swagger::WarningWriter.instance.issued_warnings?
|
58
|
+
['warnings issued']
|
59
|
+
else
|
60
|
+
[]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def consumes
|
65
|
+
if params_in_body?
|
66
|
+
['application/json']
|
67
|
+
else
|
68
|
+
['application/x-www-form-urlencoded', 'multipart/form-data']
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def params_in_body?
|
73
|
+
Apipie.configuration.generator.swagger.content_type_input == :json
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param [Apipie::Generator::Swagger::MethodDescription::ApiDecorator] api
|
77
|
+
def responses(api)
|
78
|
+
Apipie::Generator::Swagger::MethodDescription::ResponseService
|
79
|
+
.new(
|
80
|
+
@method_description,
|
81
|
+
language: @language,
|
82
|
+
http_method: api.normalized_http_method
|
83
|
+
)
|
84
|
+
.call
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::Decorator < SimpleDelegator
|
2
|
+
# @return [String]
|
3
|
+
def operation_id
|
4
|
+
"#{object.resource.controller.name}__#{object.method_name}"
|
5
|
+
end
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
def ruby_name
|
9
|
+
if object.blank?
|
10
|
+
'<no method>'
|
11
|
+
else
|
12
|
+
"#{object.resource.controller.name}##{object.method_name}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# @return [Apipie::MethodDescription, nil]
|
19
|
+
def object
|
20
|
+
__getobj__
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::ParametersService
|
2
|
+
# @param [Apipie::Generator::Swagger::MethodDescription::Decorator] method_description
|
3
|
+
# @param [Apipie::Generator::Swagger::PathDecorator] path
|
4
|
+
# @param [Symbol] http_method
|
5
|
+
def initialize(method_description, path:, http_method:)
|
6
|
+
@method_description = method_description
|
7
|
+
@path = path
|
8
|
+
@http_method = http_method
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Array]
|
12
|
+
def call
|
13
|
+
path_params_schema + body_params_schema + header_params_schema
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def path_params_schema
|
19
|
+
Apipie::Generator::Swagger::ParamDescription::PathParamsComposite.new(
|
20
|
+
path_param_descriptions,
|
21
|
+
Apipie::Generator::Swagger::Context.new(
|
22
|
+
allow_null: false,
|
23
|
+
default_in_value: 'path',
|
24
|
+
http_method: @http_method,
|
25
|
+
controller_method: @method_description
|
26
|
+
)
|
27
|
+
).to_swagger
|
28
|
+
end
|
29
|
+
|
30
|
+
def body_params_schema
|
31
|
+
if params_in_body? && body_allowed_for_current_method?
|
32
|
+
composite = Apipie::Generator::Swagger::ParamDescription::Composite.new(
|
33
|
+
body_param_descriptions,
|
34
|
+
Apipie::Generator::Swagger::Context.new(
|
35
|
+
allow_null: false,
|
36
|
+
http_method: @http_method,
|
37
|
+
controller_method: @method_description
|
38
|
+
)
|
39
|
+
)
|
40
|
+
|
41
|
+
if Apipie.configuration.generator.swagger.json_input_uses_refs?
|
42
|
+
composite = composite
|
43
|
+
.referenced("#{@method_description.operation_id}_input")
|
44
|
+
end
|
45
|
+
|
46
|
+
swagger_schema_for_body = composite.to_swagger
|
47
|
+
|
48
|
+
swagger_body_param = {
|
49
|
+
name: 'body',
|
50
|
+
in: 'body',
|
51
|
+
schema: swagger_schema_for_body
|
52
|
+
}
|
53
|
+
|
54
|
+
if swagger_schema_for_body.present?
|
55
|
+
[swagger_body_param]
|
56
|
+
else
|
57
|
+
[]
|
58
|
+
end
|
59
|
+
else
|
60
|
+
Apipie::Generator::Swagger::ParamDescription::PathParamsComposite.new(
|
61
|
+
body_param_descriptions,
|
62
|
+
Apipie::Generator::Swagger::Context.new(
|
63
|
+
allow_null: false,
|
64
|
+
http_method: @http_method,
|
65
|
+
controller_method: @method_description
|
66
|
+
)
|
67
|
+
).to_swagger
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def all_params
|
72
|
+
@all_params ||=
|
73
|
+
begin
|
74
|
+
param_names_from_method = @method_description.params.keys
|
75
|
+
missing = @path.param_names - param_names_from_method
|
76
|
+
|
77
|
+
result = @method_description.params
|
78
|
+
|
79
|
+
missing.each do |name|
|
80
|
+
warn_path_parameter_not_described(name, @path)
|
81
|
+
|
82
|
+
result[name.to_sym] = Apipie::Generator::Swagger::ParamDescription
|
83
|
+
.create_for_missing_param(@method_description, name)
|
84
|
+
end
|
85
|
+
|
86
|
+
result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def body_param_descriptions
|
91
|
+
@body_param_descriptions ||= all_params
|
92
|
+
.reject { |k, _| @path.param?(k) }
|
93
|
+
.values
|
94
|
+
end
|
95
|
+
|
96
|
+
def path_param_descriptions
|
97
|
+
@path_param_descriptions ||= all_params
|
98
|
+
.select { |k, _| @path.param?(k) }
|
99
|
+
.each { |_, desc| desc.required = true }
|
100
|
+
.values
|
101
|
+
end
|
102
|
+
|
103
|
+
# @return [Array]
|
104
|
+
def header_params_schema
|
105
|
+
return [] if @method_description.headers.blank?
|
106
|
+
|
107
|
+
@method_description.headers.map do |header|
|
108
|
+
header_hash = {
|
109
|
+
name: header[:name],
|
110
|
+
in: 'header',
|
111
|
+
required: header[:options][:required],
|
112
|
+
description: header[:description],
|
113
|
+
type: header[:options][:type] || 'string'
|
114
|
+
|
115
|
+
}
|
116
|
+
if header[:options][:default]
|
117
|
+
header_hash[:default] = header[:options][:default]
|
118
|
+
end
|
119
|
+
|
120
|
+
header_hash
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def params_in_body?
|
125
|
+
Apipie.configuration.generator.swagger.content_type_input == :json
|
126
|
+
end
|
127
|
+
|
128
|
+
def body_allowed_for_current_method?
|
129
|
+
%w[get head].exclude?(@http_method)
|
130
|
+
end
|
131
|
+
|
132
|
+
def warn_path_parameter_not_described(name, path)
|
133
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
134
|
+
Apipie::Generator::Swagger::Warning::PATH_PARAM_NOT_DESCRIBED_CODE,
|
135
|
+
@method_description.ruby_name,
|
136
|
+
{ name: name, path: path }
|
137
|
+
).warn_through_writer
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService
|
2
|
+
# @param [Apipie::ResponseDescription, Apipie::ResponseDescriptionAdapter] response_description
|
3
|
+
def initialize(response_description, allow_null:, http_method:, controller_method:)
|
4
|
+
@response_description = response_description
|
5
|
+
@allow_null = allow_null
|
6
|
+
@http_method = http_method
|
7
|
+
@controller_method = controller_method
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_swagger
|
11
|
+
composite = Apipie::Generator::Swagger::ParamDescription::Composite.new(
|
12
|
+
@response_description.params_ordered,
|
13
|
+
Apipie::Generator::Swagger::Context.new(
|
14
|
+
allow_null: @allow_null,
|
15
|
+
http_method: @http_method,
|
16
|
+
controller_method: @controller_method
|
17
|
+
)
|
18
|
+
)
|
19
|
+
|
20
|
+
if Apipie.configuration.generator.swagger.responses_use_refs? && @response_description.typename.present?
|
21
|
+
composite = composite.referenced(@response_description.typename)
|
22
|
+
end
|
23
|
+
|
24
|
+
schema = composite.to_swagger
|
25
|
+
|
26
|
+
if @response_description.is_array? && schema
|
27
|
+
schema = { type: type_for_array, items: schema }
|
28
|
+
end
|
29
|
+
|
30
|
+
if @response_description.allow_additional_properties
|
31
|
+
schema[:additionalProperties] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
schema
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def type_for_array
|
40
|
+
if @allow_null == true
|
41
|
+
%w[array null]
|
42
|
+
else
|
43
|
+
'array'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Apipie::Generator::Swagger::MethodDescription::ResponseService
|
2
|
+
# @param [Apipie::Generator::Swagger::MethodDescription::Decorator] method_description
|
3
|
+
# @param [Symbol] http_method
|
4
|
+
def initialize(method_description, http_method:, language:)
|
5
|
+
@method_description = method_description
|
6
|
+
@http_method = http_method
|
7
|
+
@language = language
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Hash]
|
11
|
+
def call
|
12
|
+
result = {}
|
13
|
+
result.merge!(errors)
|
14
|
+
result.merge!(responses)
|
15
|
+
result.merge!(empty_returns)
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @return [Hash]
|
23
|
+
def errors
|
24
|
+
@errors ||= @method_description.errors.each_with_object({}) do |error, errors|
|
25
|
+
errors[error.code] = {
|
26
|
+
description: Apipie.app.translate(error.description, @language)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Hash]
|
32
|
+
def responses
|
33
|
+
@responses ||=
|
34
|
+
@method_description.returns.each_with_object({}) do |response, responses_schema|
|
35
|
+
responses_schema[response.code] = {
|
36
|
+
description: Apipie.app.translate(response.description, @language),
|
37
|
+
schema: Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new(
|
38
|
+
response,
|
39
|
+
allow_null: false,
|
40
|
+
http_method: @http_method,
|
41
|
+
controller_method: @method_description
|
42
|
+
).to_swagger
|
43
|
+
}.compact
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Hash]
|
48
|
+
def empty_returns
|
49
|
+
return {} if errors.present? || responses.present?
|
50
|
+
|
51
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
52
|
+
Apipie::Generator::Swagger::Warning::NO_RETURN_CODES_SPECIFIED_CODE,
|
53
|
+
@method_description.ruby_name
|
54
|
+
).warn_through_writer
|
55
|
+
|
56
|
+
{ 200 => { description: 'ok' } }
|
57
|
+
end
|
58
|
+
end
|
@@ -22,7 +22,7 @@ class Apipie::Generator::Swagger::OperationId
|
|
22
22
|
# @return [Apipie::Generator::Swagger::OperationId]
|
23
23
|
def self.from(describable, param: nil)
|
24
24
|
path, http_method =
|
25
|
-
if describable.
|
25
|
+
if describable.respond_to?(:path) && describable.respond_to?(:http_method)
|
26
26
|
[describable.path, describable.http_method]
|
27
27
|
elsif describable.is_a?(Apipie::MethodDescription)
|
28
28
|
[describable.apis.first.path, describable.apis.first.http_method]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Apipie::Generator::Swagger::ParamDescription::Builder
|
2
2
|
# @param [Apipie::ParamDescription] param_description
|
3
3
|
# @param [TrueClass, FalseClass] in_schema
|
4
|
-
# @param [
|
4
|
+
# @param [Apipie::MethodDescription] controller_method
|
5
5
|
def initialize(param_description, in_schema:, controller_method:)
|
6
6
|
@param_description = param_description
|
7
7
|
@in_schema = in_schema
|
@@ -88,16 +88,16 @@ class Apipie::Generator::Swagger::ParamDescription::Builder
|
|
88
88
|
|
89
89
|
def warn_optional_without_default_value(definition)
|
90
90
|
if !required? && !definition.key?(:default)
|
91
|
-
|
91
|
+
method_id =
|
92
92
|
if @param_description.is_a?(Apipie::ResponseDescriptionAdapter::PropDesc)
|
93
93
|
@controller_method
|
94
94
|
else
|
95
|
-
@
|
95
|
+
Apipie::Generator::Swagger::MethodDescription::Decorator.new(@controller_method).ruby_name
|
96
96
|
end
|
97
97
|
|
98
98
|
Apipie::Generator::Swagger::Warning.for_code(
|
99
99
|
Apipie::Generator::Swagger::Warning::OPTIONAL_WITHOUT_DEFAULT_VALUE_CODE,
|
100
|
-
|
100
|
+
method_id,
|
101
101
|
{ parameter: @param_description.name }
|
102
102
|
).warn_through_writer
|
103
103
|
end
|
@@ -74,7 +74,7 @@ class Apipie::Generator::Swagger::ParamDescription::Composite
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
if !Apipie.configuration.
|
77
|
+
if !Apipie.configuration.generator.swagger.allow_additional_properties_in_response
|
78
78
|
@schema[:additionalProperties] = false
|
79
79
|
end
|
80
80
|
|
@@ -85,6 +85,14 @@ class Apipie::Generator::Swagger::ParamDescription::Composite
|
|
85
85
|
@schema
|
86
86
|
end
|
87
87
|
|
88
|
+
# @param [Symbol, String] param_type
|
89
|
+
#
|
90
|
+
# @return [Apipie::Generator::Swagger::ParamDescription::ReferencedComposite]
|
91
|
+
def referenced(param_type)
|
92
|
+
Apipie::Generator::Swagger::ParamDescription::ReferencedComposite.
|
93
|
+
new(self, param_type)
|
94
|
+
end
|
95
|
+
|
88
96
|
private
|
89
97
|
|
90
98
|
def for_array(schema)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Apipie::Generator::Swagger::ParamDescription::PathParamsComposite
|
2
|
+
# @param [Array<Apipie::ParamDescription>] param_descriptions
|
3
|
+
# @param [Apipie::Generator::Swagger::Context] context
|
4
|
+
def initialize(param_descriptions, context)
|
5
|
+
@param_descriptions = param_descriptions
|
6
|
+
@context = context
|
7
|
+
@result = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Array]
|
11
|
+
def to_swagger
|
12
|
+
@param_descriptions.each do |desc|
|
13
|
+
context = @context.dup
|
14
|
+
|
15
|
+
type = Apipie::Generator::Swagger::TypeExtractor.new(desc.validator).extract
|
16
|
+
|
17
|
+
if type == 'object' && desc.validator.params_ordered.blank?
|
18
|
+
warn_param_ignored_in_form_data(desc.name)
|
19
|
+
next
|
20
|
+
end
|
21
|
+
|
22
|
+
has_nested_params = type == 'object' &&
|
23
|
+
desc.validator.params_ordered.present?
|
24
|
+
|
25
|
+
if has_nested_params
|
26
|
+
context.add_to_prefix!(desc.name)
|
27
|
+
|
28
|
+
out = Apipie::Generator::Swagger::ParamDescription::PathParamsComposite
|
29
|
+
.new(desc.validator.params_ordered, context)
|
30
|
+
.to_swagger
|
31
|
+
|
32
|
+
@result.concat(out)
|
33
|
+
else
|
34
|
+
param_entry =
|
35
|
+
Apipie::Generator::Swagger::ParamDescription::Builder
|
36
|
+
.new(desc, in_schema: false, controller_method: context.controller_method)
|
37
|
+
.with_description(language: context.language)
|
38
|
+
.with_name(prefix: context.prefix)
|
39
|
+
.with_type(with_null: context.allow_null?)
|
40
|
+
.with_in(
|
41
|
+
http_method: context.http_method,
|
42
|
+
default_in_value: context.default_in_value
|
43
|
+
).to_swagger
|
44
|
+
|
45
|
+
@result << param_entry
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
@result.sort_by { |p| p[:required] ? 0 : 1 }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def warn_param_ignored_in_form_data(name)
|
55
|
+
Apipie::Generator::Swagger::Warning.for_code(
|
56
|
+
Apipie::Generator::Swagger::Warning::PARAM_IGNORED_IN_FORM_DATA_CODE,
|
57
|
+
@context.controller_method.ruby_name,
|
58
|
+
{ parameter: name }
|
59
|
+
).warn_through_writer
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# A Composite that keeps track when a param description has been added to references
|
2
|
+
# and returns the reference instead of the complete object
|
3
|
+
class Apipie::Generator::Swagger::ParamDescription::ReferencedComposite
|
4
|
+
# @param [Apipie::Generator::Swagger::ParamDescription::Composite] composite
|
5
|
+
# @param [Symbol, String] param_type
|
6
|
+
def initialize(composite, param_type)
|
7
|
+
@composite = composite
|
8
|
+
@param_type = param_type.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_swagger
|
12
|
+
return ref_to(:name) if added?(:name)
|
13
|
+
|
14
|
+
schema_obj = @composite.to_swagger
|
15
|
+
|
16
|
+
return nil if schema_obj.nil?
|
17
|
+
|
18
|
+
add(schema_obj)
|
19
|
+
|
20
|
+
{ '$ref' => ref_to(@param_type) }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def ref_to(name)
|
26
|
+
"#/definitions/#{name}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def add(schema)
|
30
|
+
Apipie::Generator::Swagger::ReferencedDefinitions.instance.add!(@param_type, schema)
|
31
|
+
end
|
32
|
+
|
33
|
+
def added?(name)
|
34
|
+
Apipie::Generator::Swagger::ReferencedDefinitions.instance.added?(name)
|
35
|
+
end
|
36
|
+
end
|
@@ -44,7 +44,7 @@ class Apipie::Generator::Swagger::ParamDescription::Type
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def params_in_body_use_reference?
|
47
|
-
Apipie.configuration.
|
47
|
+
Apipie.configuration.generator.swagger.json_input_uses_refs
|
48
48
|
end
|
49
49
|
|
50
50
|
# @return [Apipie::Generator::Swagger::Type, String]
|
@@ -99,9 +99,16 @@ class Apipie::Generator::Swagger::ParamDescription::Type
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def warn_hash_without_internal_typespec
|
102
|
+
method_id =
|
103
|
+
if @param_description.is_a?(Apipie::ResponseDescriptionAdapter::PropDesc)
|
104
|
+
@controller_method.method
|
105
|
+
else
|
106
|
+
Apipie::Generator::Swagger::MethodDescription::Decorator.new(@param_description.method_description).ruby_name
|
107
|
+
end
|
108
|
+
|
102
109
|
Apipie::Generator::Swagger::Warning.for_code(
|
103
110
|
Apipie::Generator::Swagger::Warning::HASH_WITHOUT_INTERNAL_TYPESPEC_CODE,
|
104
|
-
|
111
|
+
method_id,
|
105
112
|
{ parameter: @param_description.name }
|
106
113
|
).warn_through_writer
|
107
114
|
end
|