apipie-rails 0.5.20 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +12 -21
  3. data/.github/workflows/rubocop-challenger.yml +28 -0
  4. data/.github/workflows/rubocop.yml +18 -0
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +128 -0
  7. data/.rubocop_todo.yml +2062 -0
  8. data/.vscode/settings.json +3 -0
  9. data/CHANGELOG.md +144 -0
  10. data/Gemfile +20 -0
  11. data/README.rst +106 -15
  12. data/Rakefile +0 -5
  13. data/apipie-rails.gemspec +18 -9
  14. data/app/controllers/apipie/apipies_controller.rb +14 -29
  15. data/app/helpers/apipie_helper.rb +1 -1
  16. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +70 -41
  17. data/app/public/apipie/javascripts/bundled/bootstrap.js +1033 -479
  18. data/app/public/apipie/javascripts/bundled/jquery.js +5 -5
  19. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +9 -12
  20. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +9 -689
  21. data/app/views/apipie/apipies/_deprecation.html.erb +16 -0
  22. data/app/views/apipie/apipies/_params.html.erb +7 -1
  23. data/config/locales/en.yml +8 -0
  24. data/config/locales/ko.yml +31 -0
  25. data/gemfiles/Gemfile.tools +9 -0
  26. data/lib/apipie/apipie_module.rb +7 -7
  27. data/lib/apipie/application.rb +132 -97
  28. data/lib/apipie/configuration.rb +43 -33
  29. data/lib/apipie/dsl_definition.rb +39 -27
  30. data/lib/apipie/error_description.rb +3 -3
  31. data/lib/apipie/errors.rb +16 -16
  32. data/lib/apipie/extractor/collector.rb +4 -5
  33. data/lib/apipie/extractor/recorder.rb +33 -6
  34. data/lib/apipie/extractor/writer.rb +14 -14
  35. data/lib/apipie/extractor.rb +6 -9
  36. data/lib/apipie/generator/config.rb +12 -0
  37. data/lib/apipie/generator/generator.rb +2 -0
  38. data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
  39. data/lib/apipie/generator/swagger/config.rb +80 -0
  40. data/lib/apipie/generator/swagger/context.rb +38 -0
  41. data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
  42. data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +89 -0
  43. data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
  44. data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
  45. data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
  46. data/lib/apipie/generator/swagger/method_description/response_service.rb +58 -0
  47. data/lib/apipie/generator/swagger/method_description.rb +2 -0
  48. data/lib/apipie/generator/swagger/operation_id.rb +51 -0
  49. data/lib/apipie/generator/swagger/param_description/builder.rb +105 -0
  50. data/lib/apipie/generator/swagger/param_description/composite.rb +119 -0
  51. data/lib/apipie/generator/swagger/param_description/description.rb +15 -0
  52. data/lib/apipie/generator/swagger/param_description/in.rb +37 -0
  53. data/lib/apipie/generator/swagger/param_description/name.rb +18 -0
  54. data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
  55. data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
  56. data/lib/apipie/generator/swagger/param_description/type.rb +115 -0
  57. data/lib/apipie/generator/swagger/param_description.rb +18 -0
  58. data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
  59. data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
  60. data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
  61. data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
  62. data/lib/apipie/generator/swagger/schema.rb +63 -0
  63. data/lib/apipie/generator/swagger/swagger.rb +2 -0
  64. data/lib/apipie/generator/swagger/type.rb +16 -0
  65. data/lib/apipie/generator/swagger/type_extractor.rb +51 -0
  66. data/lib/apipie/generator/swagger/warning.rb +74 -0
  67. data/lib/apipie/generator/swagger/warning_writer.rb +54 -0
  68. data/lib/apipie/helpers.rb +3 -3
  69. data/lib/apipie/markup.rb +9 -8
  70. data/lib/apipie/method_description/api.rb +12 -0
  71. data/lib/apipie/method_description/apis_service.rb +82 -0
  72. data/lib/apipie/method_description.rb +12 -56
  73. data/lib/apipie/param_description/deprecation.rb +24 -0
  74. data/lib/apipie/param_description.rb +57 -24
  75. data/lib/apipie/resource_description.rb +42 -14
  76. data/lib/apipie/response_description.rb +3 -3
  77. data/lib/apipie/response_description_adapter.rb +10 -8
  78. data/lib/apipie/routing.rb +1 -1
  79. data/lib/apipie/rspec/response_validation_helper.rb +3 -3
  80. data/lib/apipie/static_dispatcher.rb +3 -1
  81. data/lib/apipie/swagger_generator.rb +28 -691
  82. data/lib/apipie/validator.rb +40 -10
  83. data/lib/apipie/version.rb +1 -1
  84. data/lib/apipie-rails.rb +36 -5
  85. data/lib/generators/apipie/install/install_generator.rb +1 -1
  86. data/lib/generators/apipie/views_generator.rb +1 -1
  87. data/lib/tasks/apipie.rake +35 -30
  88. data/spec/controllers/api/v2/architectures_controller_spec.rb +10 -3
  89. data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
  90. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +18 -2
  91. data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
  92. data/spec/controllers/included_param_group_controller_spec.rb +13 -0
  93. data/spec/{lib/swagger/response_validation_spec.rb → controllers/pets_controller_spec.rb} +26 -32
  94. data/spec/controllers/users_controller_spec.rb +47 -6
  95. data/spec/dummy/Rakefile +1 -1
  96. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +2 -1
  97. data/spec/dummy/app/controllers/api/v2/base_controller.rb +6 -0
  98. data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
  99. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +2 -2
  100. data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
  101. data/spec/dummy/app/controllers/concerns_controller.rb +1 -1
  102. data/spec/dummy/app/controllers/{concerns/extending_concern.rb → extending_concern.rb} +0 -2
  103. data/spec/dummy/app/controllers/included_param_group_controller.rb +19 -0
  104. data/spec/dummy/app/controllers/overridden_concerns_controller.rb +2 -2
  105. data/spec/dummy/app/controllers/pets_controller.rb +4 -4
  106. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +2 -2
  107. data/spec/dummy/app/controllers/{concerns/sample_controller.rb → sample_controller.rb} +0 -2
  108. data/spec/dummy/app/controllers/twitter_example_controller.rb +2 -2
  109. data/spec/dummy/app/controllers/users_controller.rb +17 -5
  110. data/spec/dummy/app/helpers/random_param_group.rb +8 -0
  111. data/spec/dummy/components/test_engine/test_engine.gemspec +1 -1
  112. data/spec/dummy/config/application.rb +2 -5
  113. data/spec/dummy/config/boot.rb +2 -2
  114. data/spec/dummy/config/environment.rb +1 -1
  115. data/spec/dummy/config/environments/development.rb +0 -3
  116. data/spec/dummy/config/environments/production.rb +0 -3
  117. data/spec/dummy/config/environments/test.rb +0 -5
  118. data/spec/dummy/config/initializers/apipie.rb +2 -2
  119. data/spec/dummy/config/routes.rb +8 -0
  120. data/spec/dummy/config.ru +1 -1
  121. data/spec/dummy/script/rails +2 -2
  122. data/spec/{controllers → lib/apipie}/apipies_controller_spec.rb +95 -23
  123. data/spec/lib/apipie/application_spec.rb +62 -0
  124. data/spec/lib/apipie/configuration_spec.rb +38 -0
  125. data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
  126. data/spec/lib/apipie/extractor/recorder_spec.rb +77 -0
  127. data/spec/lib/{extractor → apipie/extractor}/writer_spec.rb +8 -6
  128. data/spec/lib/{file_handler_spec.rb → apipie/file_handler_spec.rb} +7 -0
  129. data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
  130. data/spec/lib/apipie/generator/swagger/context_spec.rb +56 -0
  131. data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +119 -0
  132. data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
  133. data/spec/lib/apipie/generator/swagger/operation_id_spec.rb +63 -0
  134. data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +203 -0
  135. data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +95 -0
  136. data/spec/lib/apipie/generator/swagger/param_description/description_spec.rb +79 -0
  137. data/spec/lib/apipie/generator/swagger/param_description/in_spec.rb +86 -0
  138. data/spec/lib/apipie/generator/swagger/param_description/name_spec.rb +81 -0
  139. data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +178 -0
  140. data/spec/lib/apipie/generator/swagger/param_description_spec.rb +28 -0
  141. data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
  142. data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
  143. data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
  144. data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
  145. data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
  146. data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +38 -0
  147. data/spec/lib/apipie/generator/swagger/warning_spec.rb +51 -0
  148. data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +71 -0
  149. data/spec/lib/apipie/method_description/apis_service_spec.rb +60 -0
  150. data/spec/lib/apipie/method_description_spec.rb +133 -0
  151. data/spec/lib/apipie/no_documented_method_spec.rb +17 -0
  152. data/spec/lib/apipie/param_description/deprecation_spec.rb +31 -0
  153. data/spec/lib/{param_description_spec.rb → apipie/param_description_spec.rb} +332 -6
  154. data/spec/lib/{param_group_spec.rb → apipie/param_group_spec.rb} +6 -5
  155. data/spec/lib/apipie/resource_description_spec.rb +91 -0
  156. data/spec/lib/apipie/response_does_not_match_swagger_schema_spec.rb +35 -0
  157. data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
  158. data/spec/lib/{validator_spec.rb → apipie/validator_spec.rb} +48 -12
  159. data/spec/lib/rake_spec.rb +3 -5
  160. data/spec/lib/swagger/openapi_2_0_schema.json +8 -1
  161. data/spec/lib/swagger/rake_swagger_spec.rb +24 -9
  162. data/spec/lib/swagger/swagger_dsl_spec.rb +18 -12
  163. data/spec/lib/validators/array_validator_spec.rb +1 -1
  164. data/spec/spec_helper.rb +10 -32
  165. data/spec/support/custom_bool_validator.rb +17 -0
  166. data/spec/{controllers → test_engine}/memes_controller_spec.rb +1 -1
  167. metadata +169 -122
  168. data/Gemfile +0 -1
  169. data/gemfiles/Gemfile.rails42 +0 -14
  170. data/gemfiles/Gemfile.rails42.lock +0 -160
  171. data/gemfiles/Gemfile.rails52 +0 -9
  172. data/gemfiles/Gemfile.rails60 +0 -10
  173. data/gemfiles/Gemfile.rails61 +0 -10
  174. data/spec/lib/application_spec.rb +0 -49
  175. data/spec/lib/method_description_spec.rb +0 -98
  176. data/spec/lib/resource_description_spec.rb +0 -48
  177. data/spec/support/rails-42-ruby-26.rb +0 -15
  178. /data/spec/lib/{extractor → apipie/extractor/recorder}/middleware_spec.rb +0 -0
  179. /data/spec/lib/{extractor → apipie}/extractor_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
- require 'json'
8
- require 'ostruct'
9
- require 'open3'
10
- require 'zlib' if Apipie.configuration.swagger_generate_x_computed_id_field?
11
-
12
- attr_reader :computed_interface_id
13
-
14
- def initialize(apipie)
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 json_schema_for_self_describing_class(cls, allow_nulls)
358
- adapter = ResponseDescriptionAdapter.from_self_describing_class(cls)
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
- def response_schema(response, allow_nulls=false)
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
- if responses_use_reference? && response.typename
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
- ensure
375
- @disable_default_value_warning = prev_value
376
- end
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
- if response.is_array? && schema
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 response.allow_additional_properties
386
- schema[:additionalProperties] = true
29
+ if definitions.present?
30
+ schema[:definitions] = definitions
387
31
  end
388
32
 
389
33
  schema
390
34
  end
391
35
 
392
- def swagger_responses_hash_for_method(method)
393
- result = {}
394
-
395
- for error in method.errors
396
- error_block = {description: Apipie.app.translate(error.description, @current_lang)}
397
- result[error.code] = error_block
398
- end
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