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
@@ -1,708 +1,45 @@
|
|
1
1
|
module Apipie
|
2
|
-
|
3
|
-
#--------------------------------------------------------------------------
|
4
|
-
# Configuration. Should be moved to Apipie config.
|
5
|
-
#--------------------------------------------------------------------------
|
6
2
|
class SwaggerGenerator
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@apipie = apipie
|
16
|
-
@issued_warnings = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def params_in_body?
|
20
|
-
Apipie.configuration.swagger_content_type_input == :json
|
21
|
-
end
|
22
|
-
|
23
|
-
def params_in_body_use_reference?
|
24
|
-
Apipie.configuration.swagger_json_input_uses_refs
|
25
|
-
end
|
26
|
-
|
27
|
-
def responses_use_reference?
|
28
|
-
Apipie.configuration.swagger_responses_use_refs?
|
29
|
-
end
|
30
|
-
|
31
|
-
def include_warning_tags?
|
32
|
-
Apipie.configuration.swagger_include_warning_tags
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
def generate_from_resources(version, resources, method_name, lang, clear_warnings=false)
|
37
|
-
init_swagger_vars(version, lang, clear_warnings)
|
38
|
-
|
39
|
-
@lang = lang
|
40
|
-
@only_method = method_name
|
41
|
-
add_resources(resources)
|
42
|
-
|
43
|
-
@swagger[:info]["x-computed-id"] = @computed_interface_id if Apipie.configuration.swagger_generate_x_computed_id_field?
|
44
|
-
return @swagger
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
#--------------------------------------------------------------------------
|
49
|
-
# Initialization
|
50
|
-
#--------------------------------------------------------------------------
|
51
|
-
|
52
|
-
def init_swagger_vars(version, lang, clear_warnings=false)
|
53
|
-
|
54
|
-
# docs = {
|
55
|
-
# :name => Apipie.configuration.app_name,
|
56
|
-
# :info => Apipie.app_info(version, lang),
|
57
|
-
# :copyright => Apipie.configuration.copyright,
|
58
|
-
# :doc_url => Apipie.full_url(url_args),
|
59
|
-
# :api_url => Apipie.api_base_url(version),
|
60
|
-
# :resources => _resources
|
61
|
-
# }
|
62
|
-
|
63
|
-
|
64
|
-
@swagger = {
|
65
|
-
swagger: '2.0',
|
66
|
-
info: {
|
67
|
-
title: "#{Apipie.configuration.app_name}",
|
68
|
-
description: "#{Apipie.app_info(version, lang)}#{Apipie.configuration.copyright}",
|
69
|
-
version: "#{version}",
|
70
|
-
"x-copyright" => Apipie.configuration.copyright,
|
71
|
-
},
|
72
|
-
basePath: Apipie.api_base_url(version),
|
73
|
-
consumes: [],
|
74
|
-
paths: {},
|
75
|
-
definitions: {},
|
76
|
-
tags: [],
|
77
|
-
}
|
78
|
-
|
79
|
-
if Apipie.configuration.swagger_api_host
|
80
|
-
@swagger[:host] = Apipie.configuration.swagger_api_host
|
81
|
-
end
|
82
|
-
|
83
|
-
if params_in_body?
|
84
|
-
@swagger[:consumes] = ['application/json']
|
85
|
-
@swagger[:info][:title] += " (params in:body)"
|
86
|
-
else
|
87
|
-
@swagger[:consumes] = ['application/x-www-form-urlencoded', 'multipart/form-data']
|
88
|
-
@swagger[:info][:title] += " (params in:formData)"
|
89
|
-
end
|
90
|
-
|
91
|
-
@paths = @swagger[:paths]
|
92
|
-
@definitions = @swagger[:definitions]
|
93
|
-
@tags = @swagger[:tags]
|
94
|
-
|
95
|
-
@issued_warnings = [] if clear_warnings || @issued_warnings.nil?
|
96
|
-
@computed_interface_id = 0
|
97
|
-
|
98
|
-
@current_lang = lang
|
99
|
-
end
|
100
|
-
|
101
|
-
#--------------------------------------------------------------------------
|
102
|
-
# Engine interface methods
|
103
|
-
#--------------------------------------------------------------------------
|
104
|
-
|
105
|
-
def add_resources(resources)
|
106
|
-
resources.each do |resource_name, resource_defs|
|
107
|
-
add_resource_description(resource_name, resource_defs)
|
108
|
-
add_resource_methods(resource_name, resource_defs)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def add_resource_methods(resource_name, resource_defs)
|
113
|
-
resource_defs._methods.each do |apipie_method_name, apipie_method_defs|
|
114
|
-
add_ruby_method(@paths, apipie_method_defs)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
#--------------------------------------------------------------------------
|
120
|
-
# Logging, debugging and regression-testing utilities
|
121
|
-
#--------------------------------------------------------------------------
|
122
|
-
|
123
|
-
def ruby_name_for_method(method)
|
124
|
-
return "<no method>" if method.nil?
|
125
|
-
method.resource.controller.name + "#" + method.method
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
def warn_missing_method_summary() warn 100, "missing short description for method"; end
|
130
|
-
def warn_added_missing_slash(path) warn 101,"added missing / at beginning of path: #{path}"; end
|
131
|
-
def warn_no_return_codes_specified() warn 102,"no return codes ('errors') specified"; end
|
132
|
-
def warn_hash_without_internal_typespec(param_name) warn 103,"the parameter :#{param_name} is a generic Hash without an internal type specification"; end
|
133
|
-
def warn_optional_param_in_path(param_name) warn 104, "the parameter :#{param_name} is 'in-path'. Ignoring 'not required' in DSL"; end
|
134
|
-
def warn_optional_without_default_value(param_name) warn 105,"the parameter :#{param_name} is optional but default value is not specified (use :default_value => ...)"; end
|
135
|
-
def warn_param_ignored_in_form_data(param_name) warn 106,"ignoring param :#{param_name} -- cannot include Hash without fields in a formData specification"; end
|
136
|
-
def warn_path_parameter_not_described(name,path) warn 107,"the parameter :#{name} appears in the path #{path} but is not described"; end
|
137
|
-
def warn_inferring_boolean(name) warn 108,"the parameter [#{name}] is Enum with [true,false] values. Inferring 'boolean'"; end
|
138
|
-
|
139
|
-
def warn(warning_num, msg)
|
140
|
-
suppress = Apipie.configuration.swagger_suppress_warnings
|
141
|
-
return if suppress == true
|
142
|
-
return if suppress.is_a?(Array) && suppress.include?(warning_num)
|
143
|
-
|
144
|
-
method_id = ruby_name_for_method(@current_method)
|
145
|
-
warning_id = "#{method_id}#{warning_num}#{msg}"
|
146
|
-
|
147
|
-
if @issued_warnings.include?(warning_id)
|
148
|
-
# Already issued this warning for the current method
|
149
|
-
return
|
150
|
-
end
|
151
|
-
|
152
|
-
print "WARNING (#{warning_num}): [#{method_id}] -- #{msg}\n"
|
153
|
-
@issued_warnings.push(warning_id)
|
154
|
-
@warnings_issued = true
|
155
|
-
end
|
156
|
-
|
157
|
-
def info(msg)
|
158
|
-
print "--- INFO: [#{ruby_name_for_method(@current_method)}] -- #{msg}\n"
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
# the @computed_interface_id is a number that is uniquely derived from the list of operations
|
163
|
-
# added to the swagger definition (in an order-dependent way).
|
164
|
-
# it can be used for regression testing, allowing some differentiation between changes that
|
165
|
-
# result from changes to the input and those that result from changes to the generation
|
166
|
-
# algorithms.
|
167
|
-
# note that at the moment, this only takes operation ids into account, and ignores parameter
|
168
|
-
# definitions, so it's only partially useful.
|
169
|
-
def include_op_id_in_computed_interface_id(op_id)
|
170
|
-
@computed_interface_id = Zlib::crc32("#{@computed_interface_id} #{op_id}") if Apipie.configuration.swagger_generate_x_computed_id_field?
|
171
|
-
end
|
172
|
-
|
173
|
-
#--------------------------------------------------------------------------
|
174
|
-
# Create a tag description for a described resource
|
175
|
-
#--------------------------------------------------------------------------
|
176
|
-
|
177
|
-
def tag_name_for_resource(resource)
|
178
|
-
# resource.controller
|
179
|
-
resource._id
|
180
|
-
end
|
181
|
-
|
182
|
-
def add_resource_description(resource_name, resource)
|
183
|
-
if resource._full_description
|
184
|
-
@tags << {
|
185
|
-
name: tag_name_for_resource(resource),
|
186
|
-
description: Apipie.app.translate(resource._full_description, @current_lang)
|
187
|
-
}
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
#--------------------------------------------------------------------------
|
192
|
-
# Create swagger definitions for a ruby method
|
193
|
-
#--------------------------------------------------------------------------
|
194
|
-
|
195
|
-
def add_ruby_method(paths, ruby_method)
|
196
|
-
|
197
|
-
if @only_method
|
198
|
-
return unless ruby_method.method == @only_method
|
199
|
-
else
|
200
|
-
return if !ruby_method.show
|
201
|
-
end
|
202
|
-
|
203
|
-
for api in ruby_method.apis do
|
204
|
-
# controller: ruby_method.resource.controller.name,
|
205
|
-
|
206
|
-
path = swagger_path(api.path)
|
207
|
-
paths[path] ||= {}
|
208
|
-
methods = paths[path]
|
209
|
-
@current_method = ruby_method
|
210
|
-
|
211
|
-
@warnings_issued = false
|
212
|
-
responses = swagger_responses_hash_for_method(ruby_method)
|
213
|
-
if include_warning_tags?
|
214
|
-
warning_tags = @warnings_issued ? ['warnings issued'] : []
|
215
|
-
else
|
216
|
-
warning_tags = []
|
217
|
-
end
|
218
|
-
|
219
|
-
op_id = swagger_op_id_for_path(api.http_method, api.path)
|
220
|
-
|
221
|
-
include_op_id_in_computed_interface_id(op_id)
|
222
|
-
|
223
|
-
method_key = api.http_method.downcase
|
224
|
-
@current_http_method = method_key
|
225
|
-
|
226
|
-
methods[method_key] = {
|
227
|
-
tags: [tag_name_for_resource(ruby_method.resource)] + warning_tags + ruby_method.tag_list.tags,
|
228
|
-
consumes: params_in_body? ? ['application/json'] : ['application/x-www-form-urlencoded', 'multipart/form-data'],
|
229
|
-
operationId: op_id,
|
230
|
-
summary: Apipie.app.translate(api.short_description, @current_lang),
|
231
|
-
parameters: swagger_params_array_for_method(ruby_method, api.path),
|
232
|
-
responses: responses,
|
233
|
-
description: ruby_method.full_description
|
234
|
-
}
|
235
|
-
|
236
|
-
if methods[method_key][:summary].nil?
|
237
|
-
methods[method_key].delete(:summary)
|
238
|
-
warn_missing_method_summary
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
#--------------------------------------------------------------------------
|
244
|
-
# Utilities for conversion of ruby syntax to swagger syntax
|
245
|
-
#--------------------------------------------------------------------------
|
246
|
-
|
247
|
-
def swagger_path(str)
|
248
|
-
str = str.gsub(/:(\w+)/, '{\1}')
|
249
|
-
str = str.gsub(/\/$/, '')
|
250
|
-
|
251
|
-
if str[0] != '/'
|
252
|
-
warn_added_missing_slash(str)
|
253
|
-
str = '/' + str
|
254
|
-
end
|
255
|
-
str
|
256
|
-
end
|
257
|
-
|
258
|
-
def remove_colons(str)
|
259
|
-
str.gsub(":", "_")
|
260
|
-
end
|
261
|
-
|
262
|
-
def swagger_op_id_for_method(method)
|
263
|
-
remove_colons method.resource.controller.name + "::" + method.method
|
264
|
-
end
|
265
|
-
|
266
|
-
def swagger_id_for_typename(typename)
|
267
|
-
typename
|
268
|
-
end
|
269
|
-
|
270
|
-
def swagger_op_id_for_path(http_method, path)
|
271
|
-
# using lowercase http method, because the 'swagger-codegen' tool outputs
|
272
|
-
# strange method names if the http method is in uppercase
|
273
|
-
http_method.downcase + path.gsub(/\//,'_').gsub(/:(\w+)/, '\1').gsub(/_$/,'')
|
274
|
-
end
|
275
|
-
|
276
|
-
class SwaggerTypeWithFormat
|
277
|
-
attr_reader :str_format
|
278
|
-
def initialize(type, str_format)
|
279
|
-
@type = type
|
280
|
-
@str_format = str_format
|
281
|
-
end
|
282
|
-
|
283
|
-
def to_s
|
284
|
-
@type
|
285
|
-
end
|
286
|
-
|
287
|
-
def ==(other)
|
288
|
-
other.to_s == self.to_s
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
def lookup
|
293
|
-
@lookup ||= {
|
294
|
-
numeric: "number",
|
295
|
-
hash: "object",
|
296
|
-
array: "array",
|
297
|
-
|
298
|
-
# see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
|
299
|
-
integer: SwaggerTypeWithFormat.new("integer", "int32"),
|
300
|
-
long: SwaggerTypeWithFormat.new("integer", "int64"),
|
301
|
-
number: SwaggerTypeWithFormat.new("number", nil), # here just for completeness
|
302
|
-
float: SwaggerTypeWithFormat.new("number", "float"),
|
303
|
-
double: SwaggerTypeWithFormat.new("number", "double"),
|
304
|
-
string: SwaggerTypeWithFormat.new("string", nil), # here just for completeness
|
305
|
-
byte: SwaggerTypeWithFormat.new("string", "byte"),
|
306
|
-
binary: SwaggerTypeWithFormat.new("string", "binary"),
|
307
|
-
boolean: SwaggerTypeWithFormat.new("boolean", nil), # here just for completeness
|
308
|
-
date: SwaggerTypeWithFormat.new("string", "date"),
|
309
|
-
dateTime: SwaggerTypeWithFormat.new("string", "date-time"),
|
310
|
-
password: SwaggerTypeWithFormat.new("string", "password"),
|
311
|
-
}
|
312
|
-
end
|
313
|
-
|
314
|
-
|
315
|
-
def swagger_param_type(param_desc)
|
316
|
-
if param_desc.nil?
|
317
|
-
raise("problem")
|
318
|
-
end
|
319
|
-
|
320
|
-
v = param_desc.validator
|
321
|
-
if v.nil?
|
322
|
-
return "string"
|
323
|
-
end
|
324
|
-
|
325
|
-
if v.class == Apipie::Validator::EnumValidator || (v.respond_to?(:is_enum?) && v.is_enum?)
|
326
|
-
if v.values - [true, false] == [] && [true, false] - v.values == []
|
327
|
-
warn_inferring_boolean(param_desc.name)
|
328
|
-
return "boolean"
|
329
|
-
else
|
330
|
-
return "enum"
|
331
|
-
end
|
332
|
-
elsif v.class == Apipie::Validator::HashValidator
|
333
|
-
# pp v
|
334
|
-
end
|
335
|
-
|
336
|
-
|
337
|
-
return lookup[v.expected_type.to_sym] || v.expected_type
|
338
|
-
end
|
339
|
-
|
340
|
-
|
341
|
-
#--------------------------------------------------------------------------
|
342
|
-
# Responses
|
343
|
-
#--------------------------------------------------------------------------
|
344
|
-
|
345
|
-
def json_schema_for_method_response(method, return_code, allow_nulls)
|
346
|
-
@definitions = {}
|
347
|
-
for response in method.returns
|
348
|
-
if response.code.to_s == return_code.to_s
|
349
|
-
schema = response_schema(response, allow_nulls) if response.code.to_s == return_code.to_s
|
350
|
-
schema[:definitions] = @definitions if @definitions != {}
|
351
|
-
return schema
|
352
|
-
end
|
353
|
-
end
|
354
|
-
nil
|
3
|
+
# @param [Array<Apipie::ResourceDescription] resources
|
4
|
+
def self.generate_from_resources(resources, version:, language:, clear_warnings: false)
|
5
|
+
Apipie::Generator::Swagger::Schema.new(
|
6
|
+
resources,
|
7
|
+
version: version,
|
8
|
+
language: language,
|
9
|
+
clear_warnings: clear_warnings
|
10
|
+
).generate
|
355
11
|
end
|
356
12
|
|
357
|
-
def
|
358
|
-
|
359
|
-
response_schema(adapter, allow_nulls)
|
360
|
-
end
|
13
|
+
def self.json_schema_for_method_response(method, return_code, allow_nulls)
|
14
|
+
response = method.returns.find { |response| response.code.to_s == return_code.to_s }
|
361
15
|
|
362
|
-
|
363
|
-
begin
|
364
|
-
# no need to warn about "missing default value for optional param" when processing response definitions
|
365
|
-
prev_value = @disable_default_value_warning
|
366
|
-
@disable_default_value_warning = true
|
16
|
+
return if response.blank?
|
367
17
|
|
368
|
-
|
369
|
-
schema = {"$ref" => gen_referenced_block_from_params_array(swagger_id_for_typename(response.typename), response.params_ordered, allow_nulls)}
|
370
|
-
else
|
371
|
-
schema = json_schema_obj_from_params_array(response.params_ordered, allow_nulls)
|
372
|
-
end
|
18
|
+
http_method = method.apis.first.http_method
|
373
19
|
|
374
|
-
|
375
|
-
|
376
|
-
|
20
|
+
schema = Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new(
|
21
|
+
response,
|
22
|
+
allow_null: allow_nulls,
|
23
|
+
http_method: http_method,
|
24
|
+
controller_method: method
|
25
|
+
).to_swagger
|
377
26
|
|
378
|
-
|
379
|
-
schema = {
|
380
|
-
type: allow_nulls ? ["array","null"] : "array",
|
381
|
-
items: schema
|
382
|
-
}
|
383
|
-
end
|
27
|
+
definitions = Apipie::Generator::Swagger::ReferencedDefinitions.instance.definitions
|
384
28
|
|
385
|
-
if
|
386
|
-
schema[:
|
29
|
+
if definitions.present?
|
30
|
+
schema[:definitions] = definitions
|
387
31
|
end
|
388
32
|
|
389
33
|
schema
|
390
34
|
end
|
391
35
|
|
392
|
-
def
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
for response in method.returns
|
401
|
-
swagger_response_block = {
|
402
|
-
description: response.description
|
403
|
-
}
|
404
|
-
|
405
|
-
schema = response_schema(response)
|
406
|
-
swagger_response_block[:schema] = schema if schema
|
407
|
-
|
408
|
-
result[response.code] = swagger_response_block
|
409
|
-
end
|
410
|
-
|
411
|
-
if result.length == 0
|
412
|
-
warn_no_return_codes_specified
|
413
|
-
result[200] = {description: 'ok'}
|
414
|
-
end
|
415
|
-
|
416
|
-
result
|
417
|
-
end
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
#--------------------------------------------------------------------------
|
422
|
-
# Auto-insertion of parameters that are implicitly defined in the path
|
423
|
-
#--------------------------------------------------------------------------
|
424
|
-
|
425
|
-
def param_names_from_path(path)
|
426
|
-
path.scan(/:(\w+)/).map do |ar|
|
427
|
-
ar[0].to_sym
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
def add_missing_params(method, path)
|
432
|
-
param_names_from_method = method.params.map {|name, desc| name}
|
433
|
-
missing = param_names_from_path(path) - param_names_from_method
|
434
|
-
|
435
|
-
result = method.params
|
436
|
-
|
437
|
-
missing.each do |name|
|
438
|
-
warn_path_parameter_not_described(name, path)
|
439
|
-
result[name.to_sym] = OpenStruct.new({
|
440
|
-
required: true,
|
441
|
-
_gen_added_from_path: true,
|
442
|
-
name: name,
|
443
|
-
validator: Apipie::Validator::NumberValidator.new(nil),
|
444
|
-
options: {
|
445
|
-
in: "path"
|
446
|
-
}
|
447
|
-
})
|
448
|
-
end
|
449
|
-
|
450
|
-
result
|
451
|
-
end
|
452
|
-
|
453
|
-
#--------------------------------------------------------------------------
|
454
|
-
# The core routine for creating a swagger parameter definition block.
|
455
|
-
# The output is slightly different when the parameter is inside a schema block.
|
456
|
-
#--------------------------------------------------------------------------
|
457
|
-
def swagger_atomic_param(param_desc, in_schema, name, allow_nulls)
|
458
|
-
def save_field(entry, openapi_key, v, apipie_key=openapi_key, translate=false)
|
459
|
-
if v.key?(apipie_key)
|
460
|
-
if translate
|
461
|
-
entry[openapi_key] = Apipie.app.translate(v[apipie_key], @current_lang)
|
462
|
-
else
|
463
|
-
entry[openapi_key] = v[apipie_key]
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
swagger_def = {}
|
469
|
-
swagger_def[:name] = name if !name.nil?
|
470
|
-
|
471
|
-
swg_param_type = swagger_param_type(param_desc)
|
472
|
-
swagger_def[:type] = swg_param_type.to_s
|
473
|
-
if (swg_param_type.is_a? SwaggerTypeWithFormat) && !swg_param_type.str_format.nil?
|
474
|
-
swagger_def[:format] = swg_param_type.str_format
|
475
|
-
end
|
476
|
-
|
477
|
-
if swagger_def[:type] == "array"
|
478
|
-
swagger_def[:items] = {type: "string"}
|
479
|
-
end
|
480
|
-
|
481
|
-
if swagger_def[:type] == "enum"
|
482
|
-
swagger_def[:type] = "string"
|
483
|
-
swagger_def[:enum] = param_desc.validator.values
|
484
|
-
end
|
485
|
-
|
486
|
-
if swagger_def[:type] == "object" # we only get here if there is no specification of properties for this object
|
487
|
-
swagger_def[:additionalProperties] = true
|
488
|
-
warn_hash_without_internal_typespec(param_desc.name)
|
489
|
-
end
|
490
|
-
|
491
|
-
if param_desc.is_array?
|
492
|
-
new_swagger_def = {
|
493
|
-
items: swagger_def,
|
494
|
-
type: 'array'
|
495
|
-
}
|
496
|
-
swagger_def = new_swagger_def
|
497
|
-
if allow_nulls
|
498
|
-
swagger_def[:type] = [swagger_def[:type], "null"]
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
if allow_nulls
|
503
|
-
swagger_def[:type] = [swagger_def[:type], "null"]
|
504
|
-
end
|
505
|
-
|
506
|
-
if !in_schema
|
507
|
-
swagger_def[:in] = param_desc.options.fetch(:in, @default_value_for_param_in)
|
508
|
-
swagger_def[:required] = param_desc.required if param_desc.required
|
509
|
-
end
|
510
|
-
|
511
|
-
save_field(swagger_def, :description, param_desc.options, :desc, true) unless param_desc.options[:desc].nil?
|
512
|
-
save_field(swagger_def, :default, param_desc.options, :default_value)
|
513
|
-
|
514
|
-
if param_desc.respond_to?(:_gen_added_from_path) && !param_desc.required
|
515
|
-
warn_optional_param_in_path(param_desc.name)
|
516
|
-
swagger_def[:required] = true
|
517
|
-
end
|
518
|
-
|
519
|
-
if !swagger_def[:required] && !swagger_def.key?(:default)
|
520
|
-
warn_optional_without_default_value(param_desc.name) unless @disable_default_value_warning
|
521
|
-
end
|
522
|
-
|
523
|
-
swagger_def
|
524
|
-
end
|
525
|
-
|
526
|
-
|
527
|
-
#--------------------------------------------------------------------------
|
528
|
-
# JSON schema and referenced-object generation
|
529
|
-
#--------------------------------------------------------------------------
|
530
|
-
|
531
|
-
def ref_to(name)
|
532
|
-
"#/definitions/#{name}"
|
36
|
+
def self.json_schema_for_self_describing_class(cls, allow_nulls)
|
37
|
+
Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new(
|
38
|
+
ResponseDescriptionAdapter.from_self_describing_class(cls),
|
39
|
+
allow_null: allow_nulls,
|
40
|
+
http_method: nil,
|
41
|
+
controller_method: nil
|
42
|
+
).to_swagger
|
533
43
|
end
|
534
|
-
|
535
|
-
|
536
|
-
def json_schema_obj_from_params_array(params_array, allow_nulls = false)
|
537
|
-
(param_defs, required_params) = json_schema_param_defs_from_params_array(params_array, allow_nulls)
|
538
|
-
|
539
|
-
result = {type: "object"}
|
540
|
-
result[:properties] = param_defs
|
541
|
-
result[:additionalProperties] = false unless Apipie.configuration.swagger_allow_additional_properties_in_response
|
542
|
-
result[:required] = required_params if required_params.length > 0
|
543
|
-
|
544
|
-
param_defs.length > 0 ? result : nil
|
545
|
-
end
|
546
|
-
|
547
|
-
def gen_referenced_block_from_params_array(name, params_array, allow_nulls=false)
|
548
|
-
return ref_to(:name) if @definitions.key(:name)
|
549
|
-
|
550
|
-
schema_obj = json_schema_obj_from_params_array(params_array, allow_nulls)
|
551
|
-
return nil if schema_obj.nil?
|
552
|
-
|
553
|
-
@definitions[name.to_sym] = schema_obj
|
554
|
-
ref_to(name.to_sym)
|
555
|
-
end
|
556
|
-
|
557
|
-
def json_schema_param_defs_from_params_array(params_array, allow_nulls = false)
|
558
|
-
param_defs = {}
|
559
|
-
required_params = []
|
560
|
-
|
561
|
-
params_array ||= []
|
562
|
-
|
563
|
-
|
564
|
-
for param_desc in params_array
|
565
|
-
if !param_desc.respond_to?(:required)
|
566
|
-
# pp param_desc
|
567
|
-
raise ("unexpected param_desc format")
|
568
|
-
end
|
569
|
-
|
570
|
-
required_params.push(param_desc.name.to_sym) if param_desc.required
|
571
|
-
|
572
|
-
param_type = swagger_param_type(param_desc)
|
573
|
-
|
574
|
-
if param_type == "object" && param_desc.validator.params_ordered
|
575
|
-
schema = json_schema_obj_from_params_array(param_desc.validator.params_ordered, allow_nulls)
|
576
|
-
if param_desc.additional_properties
|
577
|
-
schema[:additionalProperties] = true
|
578
|
-
end
|
579
|
-
|
580
|
-
if param_desc.is_array?
|
581
|
-
new_schema = {
|
582
|
-
type: 'array',
|
583
|
-
items: schema
|
584
|
-
}
|
585
|
-
schema = new_schema
|
586
|
-
end
|
587
|
-
|
588
|
-
if allow_nulls
|
589
|
-
# ideally we would write schema[:type] = ["object", "null"]
|
590
|
-
# but due to a bug in the json-schema gem, we need to use anyOf
|
591
|
-
# see https://github.com/ruby-json-schema/json-schema/issues/404
|
592
|
-
new_schema = {
|
593
|
-
anyOf: [schema, {type: "null"}]
|
594
|
-
}
|
595
|
-
schema = new_schema
|
596
|
-
end
|
597
|
-
param_defs[param_desc.name.to_sym] = schema if !schema.nil?
|
598
|
-
else
|
599
|
-
param_defs[param_desc.name.to_sym] = swagger_atomic_param(param_desc, true, nil, allow_nulls)
|
600
|
-
end
|
601
|
-
end
|
602
|
-
|
603
|
-
[param_defs, required_params]
|
604
|
-
end
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
#--------------------------------------------------------------------------
|
609
|
-
# swagger "Params" block generation
|
610
|
-
#--------------------------------------------------------------------------
|
611
|
-
|
612
|
-
def body_allowed_for_current_method
|
613
|
-
!(['get', 'head'].include?(@current_http_method))
|
614
|
-
end
|
615
|
-
|
616
|
-
def swagger_params_array_for_method(method, path)
|
617
|
-
|
618
|
-
swagger_result = []
|
619
|
-
all_params_hash = add_missing_params(method, path)
|
620
|
-
|
621
|
-
body_param_defs_array = all_params_hash.map {|k, v| v if !param_names_from_path(path).include?(k)}.select{|v| !v.nil?}
|
622
|
-
body_param_defs_hash = all_params_hash.select {|k, v| v if !param_names_from_path(path).include?(k)}
|
623
|
-
path_param_defs_hash = all_params_hash.select {|k, v| v if param_names_from_path(path).include?(k)}
|
624
|
-
|
625
|
-
path_param_defs_hash.each{|name,desc| desc.required = true}
|
626
|
-
add_params_from_hash(swagger_result, path_param_defs_hash, nil, "path")
|
627
|
-
|
628
|
-
if params_in_body? && body_allowed_for_current_method
|
629
|
-
if params_in_body_use_reference?
|
630
|
-
swagger_schema_for_body = {"$ref" => gen_referenced_block_from_params_array("#{swagger_op_id_for_method(method)}_input", body_param_defs_array)}
|
631
|
-
else
|
632
|
-
swagger_schema_for_body = json_schema_obj_from_params_array(body_param_defs_array)
|
633
|
-
end
|
634
|
-
|
635
|
-
swagger_body_param = {
|
636
|
-
name: 'body',
|
637
|
-
in: 'body',
|
638
|
-
schema: swagger_schema_for_body
|
639
|
-
}
|
640
|
-
swagger_result.push(swagger_body_param) if !swagger_schema_for_body.nil?
|
641
|
-
|
642
|
-
else
|
643
|
-
add_params_from_hash(swagger_result, body_param_defs_hash)
|
644
|
-
end
|
645
|
-
|
646
|
-
add_headers_from_hash(swagger_result, method.headers) if method.headers.present?
|
647
|
-
|
648
|
-
swagger_result
|
649
|
-
end
|
650
|
-
|
651
|
-
|
652
|
-
def add_headers_from_hash(swagger_params_array, headers)
|
653
|
-
swagger_headers = headers.map do |header|
|
654
|
-
header_hash = {
|
655
|
-
name: header[:name],
|
656
|
-
in: 'header',
|
657
|
-
required: header[:options][:required],
|
658
|
-
description: header[:description],
|
659
|
-
type: header[:options][:type] || 'string'
|
660
|
-
}
|
661
|
-
header_hash[:default] = header[:options][:default] if header[:options][:default]
|
662
|
-
header_hash
|
663
|
-
end
|
664
|
-
swagger_params_array.push(*swagger_headers)
|
665
|
-
end
|
666
|
-
|
667
|
-
|
668
|
-
def add_params_from_hash(swagger_params_array, param_defs, prefix=nil, default_value_for_in=nil)
|
669
|
-
|
670
|
-
if default_value_for_in
|
671
|
-
@default_value_for_param_in = default_value_for_in
|
672
|
-
else
|
673
|
-
if body_allowed_for_current_method
|
674
|
-
@default_value_for_param_in = "formData"
|
675
|
-
else
|
676
|
-
@default_value_for_param_in = "query"
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
|
681
|
-
param_defs.each do |name, desc|
|
682
|
-
|
683
|
-
if !prefix.nil?
|
684
|
-
name = "#{prefix}[#{name}]"
|
685
|
-
end
|
686
|
-
|
687
|
-
if swagger_param_type(desc) == "object"
|
688
|
-
if desc.validator.params_ordered
|
689
|
-
params_hash = Hash[desc.validator.params_ordered.map {|desc| [desc.name, desc]}]
|
690
|
-
add_params_from_hash(swagger_params_array, params_hash, name)
|
691
|
-
else
|
692
|
-
warn_param_ignored_in_form_data(desc.name)
|
693
|
-
end
|
694
|
-
else
|
695
|
-
param_entry = swagger_atomic_param(desc, false, name, false)
|
696
|
-
if param_entry[:required]
|
697
|
-
swagger_params_array.unshift(param_entry)
|
698
|
-
else
|
699
|
-
swagger_params_array.push(param_entry)
|
700
|
-
end
|
701
|
-
|
702
|
-
end
|
703
|
-
end
|
704
|
-
end
|
705
|
-
|
706
44
|
end
|
707
|
-
|
708
45
|
end
|