apipie-rails 0.5.19 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +31 -0
- data/.github/workflows/rubocop-challenger.yml +28 -0
- data/.github/workflows/rubocop.yml +18 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +128 -0
- data/.rubocop_todo.yml +2056 -0
- data/.vscode/settings.json +3 -0
- data/CHANGELOG.md +161 -0
- data/Gemfile +20 -0
- data/README.rst +117 -23
- data/Rakefile +0 -5
- data/apipie-rails.gemspec +18 -9
- data/app/controllers/apipie/apipies_controller.rb +14 -29
- data/app/helpers/apipie_helper.rb +1 -1
- data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +70 -41
- data/app/public/apipie/javascripts/bundled/bootstrap.js +1033 -479
- data/app/public/apipie/javascripts/bundled/jquery.js +5 -5
- data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +9 -12
- data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +9 -689
- data/app/views/apipie/apipies/_deprecation.html.erb +16 -0
- data/app/views/apipie/apipies/_params.html.erb +7 -1
- data/config/locales/en.yml +8 -0
- data/config/locales/ko.yml +31 -0
- data/gemfiles/Gemfile.tools +9 -0
- data/lib/apipie/apipie_module.rb +7 -7
- data/lib/apipie/application.rb +132 -97
- data/lib/apipie/configuration.rb +43 -33
- data/lib/apipie/dsl_definition.rb +44 -33
- data/lib/apipie/error_description.rb +3 -3
- data/lib/apipie/errors.rb +17 -17
- data/lib/apipie/extractor/collector.rb +5 -6
- data/lib/apipie/extractor/recorder.rb +35 -8
- data/lib/apipie/extractor/writer.rb +15 -15
- data/lib/apipie/extractor.rb +6 -9
- data/lib/apipie/generator/config.rb +12 -0
- data/lib/apipie/generator/generator.rb +2 -0
- data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
- data/lib/apipie/generator/swagger/config.rb +80 -0
- data/lib/apipie/generator/swagger/context.rb +38 -0
- data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
- data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +89 -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 +51 -0
- data/lib/apipie/generator/swagger/param_description/builder.rb +114 -0
- data/lib/apipie/generator/swagger/param_description/composite.rb +119 -0
- data/lib/apipie/generator/swagger/param_description/description.rb +15 -0
- data/lib/apipie/generator/swagger/param_description/in.rb +37 -0
- data/lib/apipie/generator/swagger/param_description/name.rb +18 -0
- 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 +128 -0
- data/lib/apipie/generator/swagger/param_description.rb +18 -0
- 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/swagger.rb +2 -0
- data/lib/apipie/generator/swagger/type.rb +16 -0
- data/lib/apipie/generator/swagger/type_extractor.rb +51 -0
- data/lib/apipie/generator/swagger/warning.rb +74 -0
- data/lib/apipie/generator/swagger/warning_writer.rb +54 -0
- data/lib/apipie/helpers.rb +3 -3
- data/lib/apipie/markup.rb +9 -8
- data/lib/apipie/method_description/api.rb +12 -0
- data/lib/apipie/method_description/apis_service.rb +82 -0
- data/lib/apipie/method_description.rb +12 -56
- data/lib/apipie/param_description/deprecation.rb +24 -0
- data/lib/apipie/param_description.rb +57 -24
- data/lib/apipie/resource_description.rb +42 -14
- data/lib/apipie/response_description.rb +3 -3
- data/lib/apipie/response_description_adapter.rb +12 -10
- data/lib/apipie/routing.rb +1 -1
- data/lib/apipie/rspec/response_validation_helper.rb +3 -3
- data/lib/apipie/static_dispatcher.rb +10 -2
- data/lib/apipie/swagger_generator.rb +28 -691
- data/lib/apipie/validator.rb +41 -11
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +36 -5
- data/lib/generators/apipie/install/install_generator.rb +1 -1
- data/lib/generators/apipie/views_generator.rb +1 -1
- data/lib/tasks/apipie.rake +37 -32
- data/rel-eng/gem_release.ipynb +41 -9
- data/spec/controllers/api/v2/architectures_controller_spec.rb +10 -3
- data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +18 -2
- data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
- data/spec/controllers/included_param_group_controller_spec.rb +13 -0
- data/spec/{lib/swagger/response_validation_spec.rb → controllers/pets_controller_spec.rb} +26 -32
- data/spec/controllers/users_controller_spec.rb +47 -6
- data/spec/dummy/Rakefile +1 -1
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +2 -1
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +6 -0
- data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
- data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +2 -2
- data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
- data/spec/dummy/app/controllers/concerns_controller.rb +1 -1
- data/spec/dummy/app/controllers/{concerns/extending_concern.rb → extending_concern.rb} +0 -2
- data/spec/dummy/app/controllers/included_param_group_controller.rb +19 -0
- data/spec/dummy/app/controllers/overridden_concerns_controller.rb +2 -2
- data/spec/dummy/app/controllers/pets_controller.rb +5 -5
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +2 -2
- data/spec/dummy/app/controllers/{concerns/sample_controller.rb → sample_controller.rb} +0 -2
- data/spec/dummy/app/controllers/twitter_example_controller.rb +2 -2
- data/spec/dummy/app/controllers/users_controller.rb +17 -5
- data/spec/dummy/app/helpers/random_param_group.rb +8 -0
- data/spec/dummy/components/test_engine/test_engine.gemspec +1 -1
- data/spec/dummy/config/application.rb +2 -5
- data/spec/dummy/config/boot.rb +2 -2
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/development.rb +0 -3
- data/spec/dummy/config/environments/production.rb +0 -3
- data/spec/dummy/config/environments/test.rb +0 -5
- data/spec/dummy/config/initializers/apipie.rb +2 -2
- data/spec/dummy/config/routes.rb +8 -0
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/script/rails +2 -2
- data/spec/{controllers → lib/apipie}/apipies_controller_spec.rb +95 -23
- data/spec/lib/apipie/application_spec.rb +62 -0
- data/spec/lib/apipie/configuration_spec.rb +38 -0
- data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
- data/spec/lib/apipie/extractor/recorder_spec.rb +77 -0
- data/spec/lib/{extractor → apipie/extractor}/writer_spec.rb +8 -6
- data/spec/lib/{extractor → apipie}/extractor_spec.rb +1 -1
- data/spec/lib/{file_handler_spec.rb → apipie/file_handler_spec.rb} +7 -0
- data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
- data/spec/lib/apipie/generator/swagger/context_spec.rb +56 -0
- data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +119 -0
- data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
- data/spec/lib/apipie/generator/swagger/operation_id_spec.rb +63 -0
- data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +215 -0
- data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +95 -0
- data/spec/lib/apipie/generator/swagger/param_description/description_spec.rb +79 -0
- data/spec/lib/apipie/generator/swagger/param_description/in_spec.rb +86 -0
- data/spec/lib/apipie/generator/swagger/param_description/name_spec.rb +81 -0
- data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +183 -0
- data/spec/lib/apipie/generator/swagger/param_description_spec.rb +28 -0
- 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 +38 -0
- data/spec/lib/apipie/generator/swagger/warning_spec.rb +51 -0
- data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +71 -0
- data/spec/lib/apipie/method_description/apis_service_spec.rb +60 -0
- data/spec/lib/apipie/method_description_spec.rb +133 -0
- data/spec/lib/apipie/no_documented_method_spec.rb +17 -0
- data/spec/lib/apipie/param_description/deprecation_spec.rb +31 -0
- data/spec/lib/{param_description_spec.rb → apipie/param_description_spec.rb} +332 -6
- data/spec/lib/{param_group_spec.rb → apipie/param_group_spec.rb} +6 -5
- data/spec/lib/apipie/resource_description_spec.rb +91 -0
- 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/{validator_spec.rb → apipie/validator_spec.rb} +48 -12
- data/spec/lib/rake_spec.rb +3 -5
- data/spec/lib/swagger/openapi_2_0_schema.json +8 -1
- data/spec/lib/swagger/rake_swagger_spec.rb +30 -10
- data/spec/lib/swagger/swagger_dsl_spec.rb +18 -12
- data/spec/lib/validators/array_validator_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -32
- data/spec/support/custom_bool_validator.rb +17 -0
- data/spec/{controllers → test_engine}/memes_controller_spec.rb +1 -1
- metadata +173 -125
- data/.travis.yml +0 -41
- data/Gemfile +0 -1
- data/Gemfile.rails41 +0 -7
- data/Gemfile.rails42 +0 -14
- data/Gemfile.rails50 +0 -9
- data/Gemfile.rails51 +0 -9
- data/Gemfile.rails60 +0 -10
- data/Gemfile.rails61 +0 -10
- data/spec/lib/application_spec.rb +0 -49
- data/spec/lib/method_description_spec.rb +0 -98
- data/spec/lib/resource_description_spec.rb +0 -48
- /data/spec/lib/{extractor → apipie/extractor/recorder}/middleware_spec.rb +0 -0
data/lib/apipie/extractor.rb
CHANGED
@@ -15,13 +15,10 @@ class Apipie::Railtie
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
app.middleware.use ::Apipie::Extractor::Recorder::Middleware
|
19
18
|
|
20
|
-
if
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
else
|
19
|
+
if Apipie.configuration.record
|
20
|
+
app.middleware.use ::Apipie::Extractor::Recorder::Middleware
|
21
|
+
|
25
22
|
ActionController::TestCase.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
|
26
23
|
ActionController::TestCase::Behavior.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
|
27
24
|
end
|
@@ -87,7 +84,7 @@ module Apipie
|
|
87
84
|
def apis_from_routes
|
88
85
|
return @apis_from_routes if @apis_from_routes
|
89
86
|
|
90
|
-
@api_prefix = Apipie.api_base_url.sub(
|
87
|
+
@api_prefix = Apipie.api_base_url.sub(%r{/$},"")
|
91
88
|
populate_api_routes
|
92
89
|
update_api_descriptions
|
93
90
|
|
@@ -160,10 +157,10 @@ module Apipie
|
|
160
157
|
def update_api_descriptions
|
161
158
|
apis_from_docs = all_apis_from_docs
|
162
159
|
@apis_from_routes.each do |(controller, action), new_apis|
|
163
|
-
method_key = "#{Apipie.
|
160
|
+
method_key = "#{Apipie.get_resource_id(controller.safe_constantize || next)}##{action}"
|
164
161
|
old_apis = apis_from_docs[method_key] || []
|
165
162
|
new_apis.each do |new_api|
|
166
|
-
new_api[:path]
|
163
|
+
new_api[:path]&.sub!(/\(\.:format\)$/,"")
|
167
164
|
old_api = old_apis.find do |api|
|
168
165
|
api[:path] == "#{@api_prefix}#{new_api[:path]}"
|
169
166
|
end
|
@@ -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,80 @@
|
|
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, :skip_default_tags].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 skip_default_tags? skip_default_tags
|
47
|
+
alias generate_x_computed_id_field? generate_x_computed_id_field
|
48
|
+
alias swagger_include_warning_tags? swagger_include_warning_tags
|
49
|
+
alias swagger_json_input_uses_refs? swagger_json_input_uses_refs
|
50
|
+
alias swagger_responses_use_refs? swagger_responses_use_refs
|
51
|
+
alias swagger_generate_x_computed_id_field? swagger_generate_x_computed_id_field
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
@content_type_input = :form_data # this can be :json or :form_data
|
55
|
+
@json_input_uses_refs = false
|
56
|
+
@include_warning_tags = false
|
57
|
+
@suppress_warnings = false # [105,100,102]
|
58
|
+
@api_host = 'localhost:3000'
|
59
|
+
@generate_x_computed_id_field = false
|
60
|
+
@allow_additional_properties_in_response = false
|
61
|
+
@responses_use_refs = true
|
62
|
+
@schemes = [:https]
|
63
|
+
@security_definitions = {}
|
64
|
+
@global_security = []
|
65
|
+
@skip_default_tags = false
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.deprecated_methods
|
69
|
+
CONFIG_ATTRIBUTES.map do |attribute|
|
70
|
+
[
|
71
|
+
:"swagger_#{attribute}=",
|
72
|
+
:"swagger_#{attribute}?",
|
73
|
+
:"swagger_#{attribute}"
|
74
|
+
]
|
75
|
+
end.flatten
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Apipie::Generator::Swagger::Context
|
2
|
+
attr_reader :default_in_value, :language, :http_method, :controller_method,
|
3
|
+
:prefix
|
4
|
+
|
5
|
+
def initialize(
|
6
|
+
allow_null:,
|
7
|
+
http_method:,
|
8
|
+
controller_method:,
|
9
|
+
prefix: nil,
|
10
|
+
default_in_value: nil,
|
11
|
+
language: nil,
|
12
|
+
in_schema: true
|
13
|
+
)
|
14
|
+
@default_in_value = default_in_value
|
15
|
+
@allow_null = allow_null
|
16
|
+
@language = language
|
17
|
+
@in_schema = in_schema
|
18
|
+
@http_method = http_method
|
19
|
+
@controller_method = controller_method
|
20
|
+
@prefix = prefix
|
21
|
+
end
|
22
|
+
|
23
|
+
def allow_null?
|
24
|
+
@allow_null == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def in_schema?
|
28
|
+
@in_schema == true
|
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
|
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,89 @@
|
|
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
|
+
tags = if Apipie.configuration.generator.swagger.skip_default_tags?
|
51
|
+
[]
|
52
|
+
else
|
53
|
+
[@method_description.resource._id]
|
54
|
+
end
|
55
|
+
tags + warning_tags + @method_description.tag_list.tags
|
56
|
+
end
|
57
|
+
|
58
|
+
def warning_tags
|
59
|
+
if Apipie.configuration.generator.swagger.include_warning_tags? &&
|
60
|
+
Apipie::Generator::Swagger::WarningWriter.instance.issued_warnings?
|
61
|
+
['warnings issued']
|
62
|
+
else
|
63
|
+
[]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def consumes
|
68
|
+
if params_in_body?
|
69
|
+
['application/json']
|
70
|
+
else
|
71
|
+
['application/x-www-form-urlencoded', 'multipart/form-data']
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def params_in_body?
|
76
|
+
Apipie.configuration.generator.swagger.content_type_input == :json
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param [Apipie::Generator::Swagger::MethodDescription::ApiDecorator] api
|
80
|
+
def responses(api)
|
81
|
+
Apipie::Generator::Swagger::MethodDescription::ResponseService
|
82
|
+
.new(
|
83
|
+
@method_description,
|
84
|
+
language: @language,
|
85
|
+
http_method: api.normalized_http_method
|
86
|
+
)
|
87
|
+
.call
|
88
|
+
end
|
89
|
+
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_value { |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
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Apipie::Generator::Swagger::OperationId
|
2
|
+
def initialize(path:, http_method:, param: nil)
|
3
|
+
@path = path
|
4
|
+
@http_method = http_method
|
5
|
+
@param = param
|
6
|
+
end
|
7
|
+
|
8
|
+
# @return [String]
|
9
|
+
def to_s
|
10
|
+
base = normalized_http_method + path
|
11
|
+
|
12
|
+
if @param.present?
|
13
|
+
"#{base}_param_#{@param}"
|
14
|
+
else
|
15
|
+
base
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Apipie::MethodDescription::Api, Apipie::MethodDescription] describable
|
20
|
+
# @param [String, Symbol, nil] param
|
21
|
+
#
|
22
|
+
# @return [Apipie::Generator::Swagger::OperationId]
|
23
|
+
def self.from(describable, param: nil)
|
24
|
+
path, http_method =
|
25
|
+
if describable.respond_to?(:path) && describable.respond_to?(:http_method)
|
26
|
+
[describable.path, describable.http_method]
|
27
|
+
elsif describable.is_a?(Apipie::MethodDescription)
|
28
|
+
[describable.apis.first.path, describable.apis.first.http_method]
|
29
|
+
end
|
30
|
+
|
31
|
+
new(path: path, http_method: http_method, param: param)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Converts an http path for example `/api/concerns/:id` to `_api_concerns_id`
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def path
|
40
|
+
@path.gsub(%r{/}, '_').gsub(/:(\w+)/, '\1').gsub(/_$/, '')
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts an http method like `GET` to `get` Using lowercase http method,
|
44
|
+
# because the 'swagger-codegen' tool outputs strange method names if the
|
45
|
+
# http method is in uppercase
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
def normalized_http_method
|
49
|
+
@http_method.to_s.downcase
|
50
|
+
end
|
51
|
+
end
|