apipie-rails 0.9.3 → 1.0.0
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/.github/workflows/rubocop.yml +2 -2
- data/.rubocop.yml +23 -14
- data/.rubocop_todo.yml +103 -487
- data/CHANGELOG.md +20 -3
- data/README.rst +12 -12
- data/app/controllers/apipie/apipies_controller.rb +6 -6
- data/app/helpers/apipie_helper.rb +1 -1
- data/lib/apipie/apipie_module.rb +5 -5
- data/lib/apipie/application.rb +81 -55
- data/lib/apipie/configuration.rb +19 -26
- data/lib/apipie/dsl_definition.rb +8 -9
- data/lib/apipie/error_description.rb +1 -1
- data/lib/apipie/errors.rb +2 -16
- data/lib/apipie/extractor/collector.rb +3 -3
- data/lib/apipie/extractor/recorder.rb +1 -1
- data/lib/apipie/extractor.rb +2 -2
- 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 +2 -2
- 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/helpers.rb +3 -3
- data/lib/apipie/method_description.rb +5 -3
- data/lib/apipie/param_description.rb +4 -2
- data/lib/apipie/resource_description.rb +11 -8
- data/lib/apipie/response_description.rb +1 -1
- data/lib/apipie/response_description_adapter.rb +3 -3
- data/lib/apipie/routing.rb +1 -1
- data/lib/apipie/rspec/response_validation_helper.rb +1 -1
- data/lib/apipie/swagger_generator.rb +27 -551
- data/lib/apipie/validator.rb +9 -5
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +17 -0
- data/lib/tasks/apipie.rake +25 -20
- 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/dummy/config.ru +1 -1
- data/spec/lib/apipie/apipies_controller_spec.rb +4 -0
- data/spec/lib/apipie/application_spec.rb +25 -15
- 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 +23 -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/no_documented_method_spec.rb +17 -0
- 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 +71 -28
- data/spec/lib/apipie/response_does_not_match_swagger_schema_spec.rb +35 -0
- data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
- data/spec/lib/apipie/validator_spec.rb +47 -11
- data/spec/lib/rake_spec.rb +1 -1
- data/spec/lib/swagger/rake_swagger_spec.rb +6 -6
- data/spec/lib/swagger/swagger_dsl_spec.rb +17 -11
- data/spec/lib/validators/array_validator_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- metadata +31 -3
data/lib/apipie/errors.rb
CHANGED
@@ -60,27 +60,13 @@ module Apipie
|
|
60
60
|
|
61
61
|
class ResponseDoesNotMatchSwaggerSchema < Error
|
62
62
|
def initialize(controller_name, method_name, response_code, error_messages, schema, returned_object)
|
63
|
-
|
64
|
-
@method_name = method_name
|
65
|
-
@response_code = response_code
|
66
|
-
@error_messages = error_messages
|
67
|
-
@schema = schema
|
68
|
-
@returned_object = returned_object
|
69
|
-
end
|
70
|
-
|
71
|
-
def to_s
|
72
|
-
"Response does not match swagger schema (#{@controller_name}##{@method_name} #{@response_code}): #{@error_messages}\nSchema: #{JSON(@schema)}\nReturned object: #{@returned_object}"
|
63
|
+
super("Response does not match swagger schema (#{controller_name}##{method_name} #{response_code}): #{error_messages}\nSchema: #{JSON(schema)}\nReturned object: #{returned_object}")
|
73
64
|
end
|
74
65
|
end
|
75
66
|
|
76
67
|
class NoDocumentedMethod < Error
|
77
68
|
def initialize(controller_name, method_name)
|
78
|
-
|
79
|
-
@controller_name = controller_name
|
80
|
-
end
|
81
|
-
|
82
|
-
def to_s
|
83
|
-
"There is no documented method #{@controller_name}##{@method_name}"
|
69
|
+
super("There is no documented method #{controller_name}##{method_name}")
|
84
70
|
end
|
85
71
|
end
|
86
72
|
end
|
@@ -19,7 +19,7 @@ module Apipie
|
|
19
19
|
def ignore_call?(record)
|
20
20
|
return true unless record[:controller]
|
21
21
|
return true if @ignored.include?(record[:controller].name)
|
22
|
-
return true if @ignored.include?("#{Apipie.
|
22
|
+
return true if @ignored.include?("#{Apipie.resource_id(record[:controller].name)}##{record[:action]}")
|
23
23
|
return true unless @api_controllers_paths.include?(controller_full_path(record[:controller]))
|
24
24
|
end
|
25
25
|
|
@@ -33,7 +33,7 @@ module Apipie
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def add_to_records(record)
|
36
|
-
key = "#{Apipie.
|
36
|
+
key = "#{Apipie.get_resource_id(record[:controller])}##{record[:action]}"
|
37
37
|
@records[key] << record
|
38
38
|
end
|
39
39
|
|
@@ -96,7 +96,7 @@ module Apipie
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def add_routes_info(desc)
|
99
|
-
api_prefix = Apipie.api_base_url.sub(
|
99
|
+
api_prefix = Apipie.api_base_url.sub(%r{/$},"")
|
100
100
|
desc[:api] = Apipie::Extractor.apis_from_routes[[desc[:controller].name, desc[:action]]]
|
101
101
|
if desc[:api]
|
102
102
|
desc[:params].each do |name, param|
|
@@ -9,7 +9,7 @@ module Apipie
|
|
9
9
|
|
10
10
|
def analyse_env(env)
|
11
11
|
@verb = env["REQUEST_METHOD"].to_sym
|
12
|
-
@path = env["PATH_INFO"].sub(
|
12
|
+
@path = env["PATH_INFO"].sub(%r{^/*},"/")
|
13
13
|
@query = env["QUERY_STRING"] unless env["QUERY_STRING"].blank?
|
14
14
|
@params = Rack::Utils.parse_nested_query(@query)
|
15
15
|
@params.merge!(env["action_dispatch.request.request_parameters"] || {})
|
data/lib/apipie/extractor.rb
CHANGED
@@ -81,7 +81,7 @@ module Apipie
|
|
81
81
|
def apis_from_routes
|
82
82
|
return @apis_from_routes if @apis_from_routes
|
83
83
|
|
84
|
-
@api_prefix = Apipie.api_base_url.sub(
|
84
|
+
@api_prefix = Apipie.api_base_url.sub(%r{/$},"")
|
85
85
|
populate_api_routes
|
86
86
|
update_api_descriptions
|
87
87
|
|
@@ -154,7 +154,7 @@ module Apipie
|
|
154
154
|
def update_api_descriptions
|
155
155
|
apis_from_docs = all_apis_from_docs
|
156
156
|
@apis_from_routes.each do |(controller, action), new_apis|
|
157
|
-
method_key = "#{Apipie.
|
157
|
+
method_key = "#{Apipie.get_resource_id(controller.safe_constantize || next)}##{action}"
|
158
158
|
old_apis = apis_from_docs[method_key] || []
|
159
159
|
new_apis.each do |new_api|
|
160
160
|
new_api[:path]&.sub!(/\(\.:format\)$/,"")
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# The {Apipie::Generator::Swagger::ComputedInterfaceId.id} is a number that is
|
2
|
+
# uniquely derived from the list of operations added to the swagger definition (in an order-dependent way).
|
3
|
+
# it can be used for regression testing, allowing some differentiation between changes that
|
4
|
+
# result from changes to the input and those that result from changes to the generation
|
5
|
+
# algorithms.
|
6
|
+
#
|
7
|
+
# @note At the moment, this only takes operation ids into account, and ignores
|
8
|
+
# parameter definitions, so it's only partially useful.
|
9
|
+
class Apipie::Generator::Swagger::ComputedInterfaceId
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@computed_interface_id = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def add!(operation_id)
|
17
|
+
@computed_interface_id = Zlib.crc32("#{@computed_interface_id} #{operation_id}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
@computed_interface_id
|
22
|
+
end
|
23
|
+
end
|
@@ -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]
|
@@ -37,7 +37,7 @@ class Apipie::Generator::Swagger::OperationId
|
|
37
37
|
#
|
38
38
|
# @return [String]
|
39
39
|
def path
|
40
|
-
@path.gsub(
|
40
|
+
@path.gsub(%r{/}, '_').gsub(/:(\w+)/, '\1').gsub(/_$/, '')
|
41
41
|
end
|
42
42
|
|
43
43
|
# Converts an http method like `GET` to `get` Using lowercase 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
|