apipie-rails-jq 1.4.3.pre.beta.pre.jq.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/build.yml +32 -0
  3. data/.github/workflows/rubocop-challenger.yml +26 -0
  4. data/.github/workflows/rubocop.yml +18 -0
  5. data/.gitignore +16 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +132 -0
  8. data/.rubocop_todo.yml +1967 -0
  9. data/.vscode/settings.json +3 -0
  10. data/APACHE-LICENSE-2.0 +202 -0
  11. data/CHANGELOG.md +693 -0
  12. data/Gemfile +19 -0
  13. data/MIT-LICENSE +20 -0
  14. data/NOTICE +4 -0
  15. data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
  16. data/README.md +2088 -0
  17. data/Rakefile +8 -0
  18. data/apipie-rails.gemspec +44 -0
  19. data/app/controllers/apipie/apipies_controller.rb +184 -0
  20. data/app/helpers/apipie_helper.rb +10 -0
  21. data/app/public/apipie/javascripts/apipie.js +6 -0
  22. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +167 -0
  23. data/app/public/apipie/javascripts/bundled/bootstrap.js +2280 -0
  24. data/app/public/apipie/javascripts/bundled/jquery.js +2 -0
  25. data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
  26. data/app/public/apipie/stylesheets/application.css +7 -0
  27. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +9 -0
  28. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +9 -0
  29. data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
  30. data/app/views/apipie/apipies/_deprecation.html.erb +16 -0
  31. data/app/views/apipie/apipies/_disqus.html.erb +13 -0
  32. data/app/views/apipie/apipies/_errors.html.erb +23 -0
  33. data/app/views/apipie/apipies/_headers.html.erb +26 -0
  34. data/app/views/apipie/apipies/_languages.erb +6 -0
  35. data/app/views/apipie/apipies/_metadata.erb +1 -0
  36. data/app/views/apipie/apipies/_method_detail.erb +63 -0
  37. data/app/views/apipie/apipies/_params.html.erb +49 -0
  38. data/app/views/apipie/apipies/_params_plain.html.erb +21 -0
  39. data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
  40. data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
  41. data/app/views/apipie/apipies/getting_started.html.erb +6 -0
  42. data/app/views/apipie/apipies/index.html.erb +56 -0
  43. data/app/views/apipie/apipies/method.html.erb +41 -0
  44. data/app/views/apipie/apipies/plain.html.erb +77 -0
  45. data/app/views/apipie/apipies/resource.html.erb +80 -0
  46. data/app/views/apipie/apipies/static.html.erb +103 -0
  47. data/app/views/layouts/apipie/apipie.html.erb +27 -0
  48. data/config/locales/de.yml +28 -0
  49. data/config/locales/en.yml +41 -0
  50. data/config/locales/es.yml +28 -0
  51. data/config/locales/fr.yml +31 -0
  52. data/config/locales/it.yml +41 -0
  53. data/config/locales/ja.yml +31 -0
  54. data/config/locales/ko.yml +32 -0
  55. data/config/locales/pl.yml +28 -0
  56. data/config/locales/pt-BR.yml +28 -0
  57. data/config/locales/ru.yml +28 -0
  58. data/config/locales/tr.yml +28 -0
  59. data/config/locales/zh-CN.yml +28 -0
  60. data/config/locales/zh-TW.yml +28 -0
  61. data/gemfiles/Gemfile.tools +9 -0
  62. data/images/screenshot-1.png +0 -0
  63. data/images/screenshot-2.png +0 -0
  64. data/lib/apipie/apipie_module.rb +83 -0
  65. data/lib/apipie/application.rb +499 -0
  66. data/lib/apipie/configuration.rb +196 -0
  67. data/lib/apipie/core_ext/route.rb +9 -0
  68. data/lib/apipie/dsl_definition.rb +630 -0
  69. data/lib/apipie/error_description.rb +46 -0
  70. data/lib/apipie/errors.rb +86 -0
  71. data/lib/apipie/extractor/collector.rb +116 -0
  72. data/lib/apipie/extractor/recorder.rb +193 -0
  73. data/lib/apipie/extractor/writer.rb +454 -0
  74. data/lib/apipie/extractor.rb +181 -0
  75. data/lib/apipie/generator/config.rb +12 -0
  76. data/lib/apipie/generator/generator.rb +2 -0
  77. data/lib/apipie/generator/swagger/computed_interface_id.rb +23 -0
  78. data/lib/apipie/generator/swagger/config.rb +80 -0
  79. data/lib/apipie/generator/swagger/context.rb +38 -0
  80. data/lib/apipie/generator/swagger/method_description/api_decorator.rb +20 -0
  81. data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +89 -0
  82. data/lib/apipie/generator/swagger/method_description/decorator.rb +22 -0
  83. data/lib/apipie/generator/swagger/method_description/parameters_service.rb +139 -0
  84. data/lib/apipie/generator/swagger/method_description/response_schema_service.rb +46 -0
  85. data/lib/apipie/generator/swagger/method_description/response_service.rb +71 -0
  86. data/lib/apipie/generator/swagger/method_description.rb +2 -0
  87. data/lib/apipie/generator/swagger/operation_id.rb +51 -0
  88. data/lib/apipie/generator/swagger/param_description/builder.rb +114 -0
  89. data/lib/apipie/generator/swagger/param_description/composite.rb +119 -0
  90. data/lib/apipie/generator/swagger/param_description/description.rb +15 -0
  91. data/lib/apipie/generator/swagger/param_description/in.rb +37 -0
  92. data/lib/apipie/generator/swagger/param_description/name.rb +18 -0
  93. data/lib/apipie/generator/swagger/param_description/path_params_composite.rb +61 -0
  94. data/lib/apipie/generator/swagger/param_description/referenced_composite.rb +36 -0
  95. data/lib/apipie/generator/swagger/param_description/type.rb +132 -0
  96. data/lib/apipie/generator/swagger/param_description.rb +18 -0
  97. data/lib/apipie/generator/swagger/path_decorator.rb +36 -0
  98. data/lib/apipie/generator/swagger/referenced_definitions.rb +17 -0
  99. data/lib/apipie/generator/swagger/resource_description_collection.rb +30 -0
  100. data/lib/apipie/generator/swagger/resource_description_composite.rb +56 -0
  101. data/lib/apipie/generator/swagger/schema.rb +63 -0
  102. data/lib/apipie/generator/swagger/swagger.rb +2 -0
  103. data/lib/apipie/generator/swagger/type.rb +16 -0
  104. data/lib/apipie/generator/swagger/type_extractor.rb +51 -0
  105. data/lib/apipie/generator/swagger/warning.rb +74 -0
  106. data/lib/apipie/generator/swagger/warning_writer.rb +54 -0
  107. data/lib/apipie/helpers.rb +73 -0
  108. data/lib/apipie/markup.rb +52 -0
  109. data/lib/apipie/method_description/api.rb +12 -0
  110. data/lib/apipie/method_description/apis_service.rb +82 -0
  111. data/lib/apipie/method_description.rb +230 -0
  112. data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
  113. data/lib/apipie/param_description/deprecation.rb +24 -0
  114. data/lib/apipie/param_description.rb +313 -0
  115. data/lib/apipie/railtie.rb +9 -0
  116. data/lib/apipie/resource_description.rb +152 -0
  117. data/lib/apipie/response_description.rb +157 -0
  118. data/lib/apipie/response_description_adapter.rb +202 -0
  119. data/lib/apipie/routes_formatter.rb +33 -0
  120. data/lib/apipie/routing.rb +16 -0
  121. data/lib/apipie/rspec/response_validation_helper.rb +194 -0
  122. data/lib/apipie/see_description.rb +39 -0
  123. data/lib/apipie/static_dispatcher.rb +75 -0
  124. data/lib/apipie/swagger_generator.rb +45 -0
  125. data/lib/apipie/tag_list_description.rb +11 -0
  126. data/lib/apipie/validator.rb +552 -0
  127. data/lib/apipie/version.rb +3 -0
  128. data/lib/apipie-rails.rb +60 -0
  129. data/lib/generators/apipie/install/README +6 -0
  130. data/lib/generators/apipie/install/install_generator.rb +25 -0
  131. data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
  132. data/lib/generators/apipie/views_generator.rb +11 -0
  133. data/lib/tasks/apipie.rake +355 -0
  134. data/rel-eng/gem_release.ipynb +398 -0
  135. data/rel-eng/packages/.readme +3 -0
  136. data/rel-eng/packages/rubygem-apipie-rails +1 -0
  137. data/rel-eng/tito.props +5 -0
  138. data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
  139. data/spec/controllers/api/v2/architectures_controller_spec.rb +19 -0
  140. data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
  141. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +27 -0
  142. data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
  143. data/spec/controllers/concerns_controller_spec.rb +42 -0
  144. data/spec/controllers/extended_controller_spec.rb +14 -0
  145. data/spec/controllers/included_param_group_controller_spec.rb +13 -0
  146. data/spec/controllers/pets_controller_spec.rb +98 -0
  147. data/spec/controllers/users_controller_spec.rb +794 -0
  148. data/spec/dummy/Rakefile +7 -0
  149. data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
  150. data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
  151. data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
  152. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +31 -0
  153. data/spec/dummy/app/controllers/api/v2/base_controller.rb +17 -0
  154. data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
  155. data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
  156. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
  157. data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
  158. data/spec/dummy/app/controllers/application_controller.rb +18 -0
  159. data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
  160. data/spec/dummy/app/controllers/extended_controller.rb +14 -0
  161. data/spec/dummy/app/controllers/extending_concern.rb +10 -0
  162. data/spec/dummy/app/controllers/files_controller.rb +5 -0
  163. data/spec/dummy/app/controllers/included_param_group_controller.rb +19 -0
  164. data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
  165. data/spec/dummy/app/controllers/pets_controller.rb +408 -0
  166. data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
  167. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
  168. data/spec/dummy/app/controllers/sample_controller.rb +39 -0
  169. data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
  170. data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
  171. data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
  172. data/spec/dummy/app/controllers/users_controller.rb +310 -0
  173. data/spec/dummy/app/helpers/random_param_group.rb +8 -0
  174. data/spec/dummy/app/views/layouts/application.html.erb +21 -0
  175. data/spec/dummy/components/test_engine/Gemfile +6 -0
  176. data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
  177. data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
  178. data/spec/dummy/components/test_engine/config/routes.rb +3 -0
  179. data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
  180. data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
  181. data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
  182. data/spec/dummy/config/application.rb +47 -0
  183. data/spec/dummy/config/boot.rb +12 -0
  184. data/spec/dummy/config/database.yml +21 -0
  185. data/spec/dummy/config/environment.rb +8 -0
  186. data/spec/dummy/config/environments/development.rb +25 -0
  187. data/spec/dummy/config/environments/production.rb +49 -0
  188. data/spec/dummy/config/environments/test.rb +33 -0
  189. data/spec/dummy/config/initializers/apipie.rb +110 -0
  190. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  191. data/spec/dummy/config/initializers/inflections.rb +10 -0
  192. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  193. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  194. data/spec/dummy/config/initializers/session_store.rb +8 -0
  195. data/spec/dummy/config/locales/en.yml +5 -0
  196. data/spec/dummy/config/routes.rb +61 -0
  197. data/spec/dummy/config.ru +4 -0
  198. data/spec/dummy/db/.gitkeep +0 -0
  199. data/spec/dummy/doc/apipie_examples.json +1 -0
  200. data/spec/dummy/doc/users/desc_from_file.md +1 -0
  201. data/spec/dummy/public/404.html +26 -0
  202. data/spec/dummy/public/422.html +26 -0
  203. data/spec/dummy/public/500.html +26 -0
  204. data/spec/dummy/public/favicon.ico +0 -0
  205. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  206. data/spec/dummy/script/rails +6 -0
  207. data/spec/lib/apipie/apipies_controller_spec.rb +345 -0
  208. data/spec/lib/apipie/application_spec.rb +62 -0
  209. data/spec/lib/apipie/configuration_spec.rb +38 -0
  210. data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
  211. data/spec/lib/apipie/extractor/recorder/middleware_spec.rb +44 -0
  212. data/spec/lib/apipie/extractor/recorder_spec.rb +77 -0
  213. data/spec/lib/apipie/extractor/writer_spec.rb +112 -0
  214. data/spec/lib/apipie/extractor_spec.rb +9 -0
  215. data/spec/lib/apipie/file_handler_spec.rb +25 -0
  216. data/spec/lib/apipie/generator/swagger/config_spec.rb +19 -0
  217. data/spec/lib/apipie/generator/swagger/context_spec.rb +56 -0
  218. data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +119 -0
  219. data/spec/lib/apipie/generator/swagger/method_description/response_schema_service_spec.rb +105 -0
  220. data/spec/lib/apipie/generator/swagger/method_description/response_service_spec.rb +62 -0
  221. data/spec/lib/apipie/generator/swagger/operation_id_spec.rb +63 -0
  222. data/spec/lib/apipie/generator/swagger/param_description/builder_spec.rb +245 -0
  223. data/spec/lib/apipie/generator/swagger/param_description/composite_spec.rb +95 -0
  224. data/spec/lib/apipie/generator/swagger/param_description/description_spec.rb +79 -0
  225. data/spec/lib/apipie/generator/swagger/param_description/in_spec.rb +86 -0
  226. data/spec/lib/apipie/generator/swagger/param_description/name_spec.rb +81 -0
  227. data/spec/lib/apipie/generator/swagger/param_description/type_spec.rb +210 -0
  228. data/spec/lib/apipie/generator/swagger/param_description_spec.rb +28 -0
  229. data/spec/lib/apipie/generator/swagger/path_decorator_spec.rb +57 -0
  230. data/spec/lib/apipie/generator/swagger/referenced_definitions_spec.rb +35 -0
  231. data/spec/lib/apipie/generator/swagger/resource_description_composite_spec.rb +37 -0
  232. data/spec/lib/apipie/generator/swagger/resource_descriptions_collection_spec.rb +57 -0
  233. data/spec/lib/apipie/generator/swagger/schema_spec.rb +89 -0
  234. data/spec/lib/apipie/generator/swagger/type_extractor_spec.rb +38 -0
  235. data/spec/lib/apipie/generator/swagger/warning_spec.rb +51 -0
  236. data/spec/lib/apipie/generator/swagger/warning_writer_spec.rb +71 -0
  237. data/spec/lib/apipie/method_description/apis_service_spec.rb +60 -0
  238. data/spec/lib/apipie/method_description_spec.rb +133 -0
  239. data/spec/lib/apipie/no_documented_method_spec.rb +17 -0
  240. data/spec/lib/apipie/param_description/deprecation_spec.rb +31 -0
  241. data/spec/lib/apipie/param_description_spec.rb +671 -0
  242. data/spec/lib/apipie/param_group_spec.rb +61 -0
  243. data/spec/lib/apipie/resource_description_spec.rb +91 -0
  244. data/spec/lib/apipie/response_description/response_object_spec.rb +22 -0
  245. data/spec/lib/apipie/response_description_spec.rb +56 -0
  246. data/spec/lib/apipie/response_does_not_match_swagger_schema_spec.rb +35 -0
  247. data/spec/lib/apipie/swagger_generator_spec.rb +94 -0
  248. data/spec/lib/apipie/validator_spec.rb +149 -0
  249. data/spec/lib/rake_spec.rb +69 -0
  250. data/spec/lib/swagger/openapi_2_0_schema.json +1614 -0
  251. data/spec/lib/swagger/rake_swagger_spec.rb +159 -0
  252. data/spec/lib/swagger/swagger_dsl_spec.rb +664 -0
  253. data/spec/lib/validators/array_validator_spec.rb +85 -0
  254. data/spec/spec_helper.rb +92 -0
  255. data/spec/support/custom_bool_validator.rb +17 -0
  256. data/spec/support/rake.rb +21 -0
  257. data/spec/test_engine/memes_controller_spec.rb +10 -0
  258. metadata +499 -0
@@ -0,0 +1,202 @@
1
+ module Apipie
2
+
3
+ def self.prop(name, expected_type, options = {}, sub_properties = [])
4
+ Apipie::ResponseDescriptionAdapter::PropDesc.new(name, expected_type, options, sub_properties)
5
+ end
6
+
7
+ def self.additional_properties(yesno)
8
+ Apipie::ResponseDescriptionAdapter::AdditionalPropertiesModifier.new(yesno)
9
+ end
10
+
11
+ class ResponseDescriptionAdapter
12
+ class Modifier
13
+ def apply(adapter)
14
+ raise "Modifier subclass must implement 'apply' method"
15
+ end
16
+ end
17
+
18
+ class AdditionalPropertiesModifier < Modifier
19
+ def initialize(additional_properties_allowed)
20
+ @additional_properties_allowed = additional_properties_allowed
21
+ end
22
+
23
+ def apply(adapter)
24
+ adapter.additional_properties = @additional_properties_allowed
25
+ end
26
+ end
27
+ end
28
+
29
+
30
+ class ResponseDescriptionAdapter
31
+
32
+ #
33
+ # A ResponseDescriptionAdapter::PropDesc object pretends to be an Apipie::Param in a ResponseDescription
34
+ #
35
+ # To successfully masquerade as such, it needs to:
36
+ # respond_to?('name') and/or ['name'] returning the name of the parameter
37
+ # respond_to?('required') and/or ['required'] returning boolean
38
+ # respond_to?('additional_properties') and/or ['additional_properties'] returning boolean
39
+ # respond_to?('validator') and/or ['validator'] returning 'nil' (so type is 'string'), or an object that:
40
+ # 1) describes a type. currently type is inferred as follows:
41
+ # if validator.is_a? Apipie::Validator::EnumValidator --> respond_to? 'values' (returns array). Type is enum or boolean
42
+ # else: use v.expected_type(). This is expected to be the swagger type, or:
43
+ # numeric ==> swagger type is 'number'
44
+ # hash ==> swagger type is 'object' and validator should respond_to? 'params_ordered'
45
+ # array ==> swagger type is array and validator (FUTURE) should indicate type of element
46
+
47
+ class PropDesc
48
+
49
+ def to_s
50
+ "PropDesc -- name: #{@name} type: #{@expected_type} required: #{@required} options: #{@options} subprop count: #{@sub_properties.length} additional properties: #{@additional_properties}"
51
+ end
52
+
53
+ #
54
+ # a ResponseDescriptionAdapter::PropDesc::Validator pretends to be an Apipie::Validator
55
+ #
56
+ class Validator
57
+ attr_reader :expected_type
58
+
59
+ def [](key)
60
+ self.send(key) if self.respond_to?(key.to_s)
61
+ end
62
+
63
+ def initialize(expected_type, enum_values = nil, sub_properties = nil)
64
+ @expected_type = expected_type
65
+ @enum_values = enum_values
66
+ @is_enum = !!enum_values
67
+ @sub_properties = sub_properties
68
+ end
69
+
70
+ def is_enum?
71
+ !!@is_enum
72
+ end
73
+
74
+ def values
75
+ @enum_values
76
+ end
77
+
78
+ def params_ordered
79
+ raise "Only validators with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
80
+ @sub_properties
81
+ end
82
+ end
83
+
84
+ #======================================================================
85
+
86
+
87
+ def initialize(name, expected_type, options = {}, sub_properties = [])
88
+ @name = name
89
+ @required = true
90
+ @required = false if options[:required] == false
91
+ @expected_type = expected_type
92
+ @additional_properties = false
93
+
94
+ options[:desc] ||= options[:description]
95
+ @description = options[:desc]
96
+ @options = options
97
+ @is_array = options[:is_array] || false
98
+ @sub_properties = []
99
+ for prop in sub_properties do
100
+ add_sub_property(prop)
101
+ end
102
+ end
103
+
104
+ def [](key)
105
+ self.send(key) if self.respond_to?(key.to_s)
106
+ end
107
+
108
+ def add_sub_property(prop_desc)
109
+ raise "Only properties with expected_type 'object' can have sub-properties" unless @expected_type == 'object'
110
+ case prop_desc
111
+ when PropDesc
112
+ @sub_properties << prop_desc
113
+ when Modifier
114
+ prop_desc.apply(self)
115
+ else
116
+ raise "Unrecognized prop_desc type (#{prop_desc.class})"
117
+ end
118
+ end
119
+
120
+ def to_json(lang)
121
+ {
122
+ name: name,
123
+ required: required,
124
+ validator: validator,
125
+ description: description,
126
+ additional_properties: additional_properties,
127
+ is_array: is_array?,
128
+ options: options
129
+ }
130
+ end
131
+ attr_reader :name, :required, :expected_type, :options, :description
132
+ attr_accessor :additional_properties
133
+
134
+ alias desc description
135
+
136
+ def is_array?
137
+ @is_array
138
+ end
139
+
140
+ def validator
141
+ Validator.new(@expected_type, options[:values], @sub_properties)
142
+ end
143
+ end
144
+ end
145
+
146
+ #======================================================================
147
+
148
+ class ResponseDescriptionAdapter
149
+
150
+ def self.from_self_describing_class(cls)
151
+ adapter = ResponseDescriptionAdapter.new(cls.to_s)
152
+ props = cls.describe_own_properties
153
+ adapter.add_property_descriptions(props)
154
+ adapter
155
+ end
156
+
157
+ def initialize(typename)
158
+ @property_descs = []
159
+ @additional_properties = false
160
+ @typename = typename
161
+ end
162
+
163
+ attr_accessor :additional_properties, :typename
164
+
165
+ def allow_additional_properties
166
+ additional_properties
167
+ end
168
+
169
+ def to_json
170
+ params_ordered.to_json
171
+ end
172
+
173
+ def add(prop_desc)
174
+ case prop_desc
175
+ when PropDesc
176
+ @property_descs << prop_desc
177
+ when Modifier
178
+ prop_desc.apply(self)
179
+ else
180
+ raise "Unrecognized prop_desc type (#{prop_desc.class})"
181
+ end
182
+ end
183
+
184
+ def add_property_descriptions(prop_descs)
185
+ for prop_desc in prop_descs
186
+ add(prop_desc)
187
+ end
188
+ end
189
+
190
+ def property(name, expected_type, options)
191
+ @property_descs << PropDesc.new(name, expected_type, options)
192
+ end
193
+
194
+ def params_ordered
195
+ @property_descs
196
+ end
197
+
198
+ def is_array?
199
+ false
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,33 @@
1
+ module Apipie
2
+ class RoutesFormatter
3
+ API_METHODS = %w{GET POST PUT PATCH OPTIONS DELETE}.freeze
4
+
5
+ # The entry method called by Apipie to extract the array
6
+ # representing the api dsl from the routes definition.
7
+ def format_routes(rails_routes, args)
8
+ rails_routes.map { |rails_route| format_route(rails_route, args) }
9
+ end
10
+
11
+ def format_route(rails_route, args)
12
+ { :path => format_path(rails_route),
13
+ :verb => format_verb(rails_route),
14
+ :desc => args[:desc],
15
+ :options => args[:options] }
16
+ end
17
+
18
+ def format_path(rails_route)
19
+ File.join(rails_route.base_url, rails_route.path.spec.to_s.gsub('(.:format)', ''))
20
+ end
21
+
22
+ def format_verb(rails_route)
23
+ verb = API_METHODS.select{|defined_verb| defined_verb =~ /\A#{rails_route.verb}\z/}
24
+ if verb.count != 1
25
+ verb = API_METHODS.select{|defined_verb| defined_verb == rails_route.constraints[:method]}
26
+ if verb.blank?
27
+ raise "Unknown verb #{rails_route.path.spec.to_s}"
28
+ end
29
+ end
30
+ verb.first
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ module Apipie
2
+ module Routing
3
+ module MapperExtensions
4
+ def apipie(options = {})
5
+ namespace "apipie", :path => Apipie.configuration.doc_base_url do
6
+ get 'apipie_checksum', :to => "apipies#apipie_checksum", :format => "json"
7
+ constraints(:version => %r{[^/]+}, :resource => %r{[^/]+}, :method => %r{[^/]+}) do
8
+ get(options.reverse_merge("(:version)/(:resource)/(:method)" => "apipies#index", :as => :apipie))
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActionDispatch::Routing::Mapper.send :include, Apipie::Routing::MapperExtensions
@@ -0,0 +1,194 @@
1
+ #----------------------------------------------------------------------------------------------
2
+ # response_validation_helper.rb:
3
+ #
4
+ # this is an rspec utility to allow validation of responses against the swagger schema generated
5
+ # from the Apipie 'returns' definition for the call.
6
+ #
7
+ #
8
+ # to use this file in a controller rspec you should
9
+ # require 'apipie/rspec/response_validation_helper' in the spec file
10
+ #
11
+ #
12
+ # this utility provides two mechanisms: matcher-based validation and auto-validation
13
+ #
14
+ # matcher-based: an rspec matcher allowing 'expect(response).to match_declared_responses'
15
+ # auto-validation: all responses returned from 'get', 'post', etc. are automatically tested
16
+ #
17
+ # ===================================
18
+ # Matcher-based validation - example
19
+ # ===================================
20
+ # Assume the file 'my_controller_spec.rb':
21
+ #
22
+ # require 'apipie/rspec/response_validation_helper'
23
+ #
24
+ # RSpec.describe MyController, :type => :controller, :show_in_doc => true do
25
+ #
26
+ # describe "GET stuff with response validation" do
27
+ # render_views # this makes sure the 'get' operation will actually
28
+ # # return the rendered view even though this is a Controller spec
29
+ #
30
+ # it "does something" do
31
+ # response = get :index, {format: :json}
32
+ #
33
+ # # the following expectation will fail if the returned object
34
+ # # does not match the 'returns' declaration in the Controller,
35
+ # # or if there is no 'returns' declaration for the returned
36
+ # # HTTP status code
37
+ # expect(response).to match_declared_responses
38
+ # end
39
+ # end
40
+ #
41
+ #
42
+ # ===================================
43
+ # Auto-validation
44
+ # ===================================
45
+ # To use auto-validation, at the beginning of the block in which you want to turn on validation:
46
+ # -) turn on view rendering (by stating 'render_views')
47
+ # -) turn on response validation by stating 'auto_validate_rendered_views'
48
+ #
49
+ # For example, assume the file 'my_controller_spec.rb':
50
+ #
51
+ # require 'apipie/rspec/response_validation_helper'
52
+ #
53
+ # RSpec.describe MyController, :type => :controller, :show_in_doc => true do
54
+ #
55
+ # describe "GET stuff with response validation" do
56
+ # render_views
57
+ # auto_validate_rendered_views
58
+ #
59
+ # it "does something" do
60
+ # get :index, {format: :json}
61
+ # end
62
+ # it "does something else" do
63
+ # get :another_index, {format: :json}
64
+ # end
65
+ # end
66
+ #
67
+ # describe "GET stuff without response validation" do
68
+ # it "does something" do
69
+ # get :index, {format: :json}
70
+ # end
71
+ # it "does something else" do
72
+ # get :another_index, {format: :json}
73
+ # end
74
+ # end
75
+ #
76
+ #
77
+ # Once this is done, responses from http operations ('get', 'post', 'delete', etc.)
78
+ # will fail the test if the response structure does not match the 'returns' declaration
79
+ # on the method (for the actual HTTP status code), or if there is no 'returns' declaration
80
+ # for the HTTP status code.
81
+ #----------------------------------------------------------------------------------------------
82
+
83
+
84
+ #----------------------------------------------------------------------------------------------
85
+ # Response validation: core logic (used by auto-validation and manual-validation mechanisms)
86
+ #----------------------------------------------------------------------------------------------
87
+ class ActionController::Base
88
+ module Apipie::ControllerValidationHelpers
89
+ # this method is injected into ActionController::Base in order to
90
+ # get access to the names of the current controller, current action, as well as to the response
91
+ def schema_validation_errors_for_response
92
+ unprocessed_schema = Apipie::json_schema_for_method_response(controller_name, action_name, response.code, true)
93
+
94
+ if unprocessed_schema.nil?
95
+ err = "no schema defined for #{controller_name}##{action_name}[#{response.code}]"
96
+ return [nil, [err], RuntimeError.new(err)]
97
+ end
98
+
99
+ schema = JSON.parse(JSON(unprocessed_schema))
100
+
101
+ error_list = JSON::Validator.fully_validate(schema, response.body, :strict => false, :version => :draft4, :json => true)
102
+
103
+ error_object = Apipie::ResponseDoesNotMatchSwaggerSchema.new(controller_name, action_name, response.code, error_list, schema, response.body)
104
+
105
+ [schema, error_list, error_object]
106
+ rescue Apipie::NoDocumentedMethod
107
+ [nil, [], nil]
108
+ end
109
+ end
110
+
111
+ include Apipie::ControllerValidationHelpers
112
+ end
113
+
114
+ module Apipie
115
+ def self.print_validation_errors(validation_errors, schema, response, error_object = nil)
116
+ Rails.logger.warn(validation_errors.to_s)
117
+ if Rails.env.test?
118
+ puts "schema validation errors:"
119
+ validation_errors.each { |e| puts "--> #{e.to_s}" }
120
+ puts "schema: #{schema.nil? ? '<none>' : JSON(schema)}"
121
+ puts "response: #{response.body}"
122
+ raise error_object if error_object
123
+ end
124
+ end
125
+ end
126
+
127
+ #---------------------------------
128
+ # Manual-validation (RSpec matcher)
129
+ #---------------------------------
130
+ RSpec::Matchers.define :match_declared_responses do
131
+ match do |actual|
132
+ (schema, validation_errors) = subject.send(:schema_validation_errors_for_response)
133
+ valid = (validation_errors == [])
134
+ Apipie::print_validation_errors(validation_errors, schema, response) unless valid
135
+
136
+ valid
137
+ end
138
+ end
139
+
140
+
141
+ #---------------------------------
142
+ # Auto-validation logic
143
+ #---------------------------------
144
+ module RSpec::Rails::ViewRendering
145
+ # Augment the RSpec DSL
146
+ module ClassMethods
147
+ def auto_validate_rendered_views
148
+ before do
149
+ @is_response_validation_on = true
150
+ end
151
+
152
+ after do
153
+ @is_response_validation_on = false
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+
160
+ ActionController::TestCase::Behavior.instance_eval do
161
+ # instrument the 'process' method in ActionController::TestCase to enable response validation
162
+ module Apipie::ResponseValidationHelpers
163
+ @is_response_validation_on = false
164
+ def process(*, **)
165
+ result = super
166
+ validate_response if @is_response_validation_on
167
+
168
+ result
169
+ end
170
+
171
+ def validate_response
172
+ controller.send(:validate_response_and_abort_with_info_if_errors)
173
+ end
174
+ end
175
+
176
+ prepend Apipie::ResponseValidationHelpers
177
+ end
178
+
179
+
180
+ class ActionController::Base
181
+ module Apipie::ControllerValidationHelpers
182
+ def validate_response_and_abort_with_info_if_errors
183
+
184
+ (schema, validation_errors, error_object) = schema_validation_errors_for_response
185
+
186
+ valid = (validation_errors == [])
187
+ if !valid
188
+ Apipie::print_validation_errors(validation_errors, schema, response, error_object)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+
@@ -0,0 +1,39 @@
1
+ module Apipie
2
+
3
+ class SeeDescription
4
+
5
+ attr_reader :link, :description
6
+
7
+ def initialize(args)
8
+ if args.first.is_a? Hash
9
+ args = args.first
10
+ elsif args.count == 2
11
+ if args.last.is_a? Hash
12
+ args = {:link => args.first}.merge(args.last)
13
+ else
14
+ args = {:link => args.first, :description => args.second}
15
+ end
16
+ elsif args.count == 1 && args.first.is_a?(String)
17
+ args = {:link => args.first, :description => args.first}
18
+ else
19
+ raise ArgumentError "ApipieError: Bad use of see method."
20
+ end
21
+ @link = args[:link] || args['link']
22
+ @description = args[:desc] || args[:description] || args['desc'] || args['description']
23
+ end
24
+
25
+ def to_json
26
+ {:link => see_url, :description => description}
27
+ end
28
+
29
+ def see_url
30
+ method_description = Apipie[@link]
31
+ if method_description.nil?
32
+ raise ArgumentError.new("Method #{@link} referenced in 'see' does not exist.")
33
+ end
34
+ method_description.doc_url
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,75 @@
1
+ module Apipie
2
+
3
+ class FileHandler
4
+ def initialize(root)
5
+ @root = root.chomp('/')
6
+ @compiled_root = /^#{Regexp.escape(root)}/
7
+ @file_server = if defined?(::Rack::Files)
8
+ ::Rack::Files.new(@root)
9
+ else
10
+ # Deprecated in Rack 3.0, kept
11
+ # for backward compatibility
12
+ ::Rack::File.new(@root)
13
+ end
14
+ end
15
+
16
+ def match?(path)
17
+ # Replace all null bytes
18
+ path = ::Rack::Utils.unescape(path || '')
19
+ .encode(Encoding::UTF_8, invalid: :replace, replace: '')
20
+ .gsub("\x0", '')
21
+
22
+ full_path = path.empty? ? @root : File.join(@root, path)
23
+ paths = "#{full_path}#{ext}"
24
+
25
+ matches = Dir[paths]
26
+ match = matches.detect { |m| File.file?(m) }
27
+ if match
28
+ match.sub!(@compiled_root, '')
29
+ match
30
+ end
31
+ end
32
+
33
+ delegate :call, to: :@file_server
34
+
35
+ def ext
36
+ @ext ||= begin
37
+ ext = cache_extension
38
+ "{,#{ext},/index#{ext}}"
39
+ end
40
+ end
41
+
42
+ def cache_extension
43
+ if ::ActionController::Base.respond_to?(:default_static_extension)
44
+ ::ActionController::Base.default_static_extension
45
+ else
46
+ ::ActionController::Base.page_cache_extension
47
+ end
48
+
49
+ end
50
+ end
51
+
52
+ class StaticDispatcher
53
+ # Dispatches the static files. Similar to ActionDispatch::Static, but
54
+ # it supports different baseurl configurations
55
+ def initialize(app, path)
56
+ @app = app
57
+ @file_handler = Apipie::FileHandler.new(path)
58
+ end
59
+
60
+ def call(env)
61
+ @baseurl ||= Apipie.configuration.doc_base_url
62
+ case env['REQUEST_METHOD']
63
+ when 'GET', 'HEAD'
64
+ path = env['PATH_INFO'].sub("#{@baseurl}/","/apipie/").chomp('/')
65
+
66
+ if match = @file_handler.match?(path)
67
+ env["PATH_INFO"] = match
68
+ return @file_handler.call(env)
69
+ end
70
+ end
71
+
72
+ @app.call(env)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,45 @@
1
+ module Apipie
2
+ class SwaggerGenerator
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
11
+ end
12
+
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 }
15
+
16
+ return if response.blank?
17
+
18
+ http_method = method.apis.first.http_method
19
+
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
26
+
27
+ definitions = Apipie::Generator::Swagger::ReferencedDefinitions.instance.definitions
28
+
29
+ if definitions.present?
30
+ schema[:definitions] = definitions
31
+ end
32
+
33
+ schema
34
+ end
35
+
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
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ module Apipie
2
+
3
+ class TagListDescription
4
+
5
+ attr_reader :tags
6
+
7
+ def initialize(tags); @tags = tags; end
8
+
9
+ end
10
+
11
+ end