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,499 @@
1
+ require 'apipie/static_dispatcher'
2
+ require 'apipie/routes_formatter'
3
+ require 'yaml'
4
+ require 'digest/sha1'
5
+ require 'json'
6
+
7
+ module Apipie
8
+
9
+ class Application
10
+ # we need engine just for serving static assets
11
+ class Engine < Rails::Engine
12
+ initializer "static assets", :before => :build_middleware_stack do |app|
13
+ app.middleware.use ::Apipie::StaticDispatcher, "#{root}/app/public"
14
+ end
15
+ end
16
+
17
+ attr_reader :resource_descriptions
18
+
19
+ def initialize
20
+ super
21
+ init_env
22
+ end
23
+
24
+ def available_versions
25
+ @resource_descriptions.keys.sort
26
+ end
27
+
28
+ def rails_routes(route_set = nil, base_url = "")
29
+ return @_rails_routes if route_set.nil? && @_rails_routes
30
+
31
+ route_set ||= Rails.application.routes
32
+ # ensure routes are loaded
33
+ Rails.application.reload_routes! unless Rails.application.routes.routes.any?
34
+
35
+ flattened_routes = []
36
+
37
+ route_set.routes.each do |route|
38
+ # route is_a ActionDispatch::Journey::Route
39
+ # route.app is_a ActionDispatch::Routing::Mapper::Constraints
40
+ # route.app.app is_a TestEngine::Engine
41
+ route_app = route.app.app
42
+ if route_app.respond_to?(:routes) && route_app.routes.is_a?(ActionDispatch::Routing::RouteSet)
43
+ # recursively go though the mounted engines
44
+ flattened_routes.concat(rails_routes(route_app.routes, File.join(base_url, route.path.spec.to_s)))
45
+ else
46
+ route.base_url = base_url
47
+ flattened_routes << route
48
+ end
49
+ end
50
+
51
+ @_rails_routes = flattened_routes
52
+ end
53
+
54
+ def rails_routes_by_controller_and_action
55
+ @_rails_routes_by_controller_and_action = rails_routes.group_by do |route|
56
+ requirements = route.requirements
57
+ [requirements[:controller], requirements[:action]]
58
+ end
59
+ end
60
+
61
+ def clear_cached_routes!
62
+ @_rails_routes = nil
63
+ @_rails_routes_by_controller_and_action = nil
64
+ end
65
+
66
+ def routes_for_action(controller, method, args)
67
+ routes = rails_routes_by_controller_and_action[[controller.name.underscore.chomp('_controller'), method.to_s]] || []
68
+
69
+ Apipie.configuration.routes_formatter.format_routes(routes, args)
70
+ end
71
+
72
+ # create new method api description
73
+ def define_method_description(controller, method_name, dsl_data)
74
+ return if ignored?(controller, method_name)
75
+ ret_method_description = nil
76
+
77
+ versions = dsl_data[:api_versions] || []
78
+ versions = controller_versions(controller) if versions.empty?
79
+
80
+ versions.each do |version|
81
+ resource_id_with_version = "#{version}##{get_resource_id(controller)}"
82
+ resource_description = get_resource_description(resource_id_with_version)
83
+
84
+ if resource_description.nil?
85
+ resource_description = define_resource_description(controller, version)
86
+ end
87
+
88
+ method_description = Apipie::MethodDescription.new(method_name, resource_description, dsl_data)
89
+
90
+ # we create separate method description for each version in
91
+ # case the method belongs to more versions. We return just one
92
+ # because the version doesn't matter for the purpose it's used
93
+ # (to wrap the original version with validators)
94
+ ret_method_description ||= method_description
95
+ resource_description.add_method_description(method_description)
96
+ end
97
+
98
+ ret_method_description
99
+ end
100
+
101
+ # create new resource api description
102
+ def define_resource_description(controller, version, dsl_data = nil)
103
+ return if ignored?(controller)
104
+
105
+ resource_id = get_resource_id(controller)
106
+ resource_description = @resource_descriptions[version][resource_id]
107
+ if resource_description
108
+ # we already defined the description somewhere (probably in
109
+ # some method. Updating just meta data from dsl
110
+ resource_description.update_from_dsl_data(dsl_data) if dsl_data
111
+ else
112
+ resource_description = Apipie::ResourceDescription.new(controller, resource_id, dsl_data, version)
113
+
114
+ Apipie.debug("@resource_descriptions[#{version}][#{resource_id}] = #{resource_description}")
115
+ @resource_descriptions[version][resource_id] ||= resource_description
116
+ end
117
+
118
+ return resource_description
119
+ end
120
+
121
+ # recursively searches what versions has the controller specified in
122
+ # resource_description? It's used to derivate the default value of
123
+ # versions for methods.
124
+ def controller_versions(controller)
125
+ value_from_parents(controller, default: [Apipie.configuration.default_version]) do |c|
126
+ ret = @controller_versions[c.to_s]
127
+ ret unless ret.empty?
128
+ end
129
+ end
130
+
131
+ # Recursively walks up the controller hierarchy looking for a value
132
+ # from the block.
133
+ # Stops at ActionController::Base.
134
+ # @param [Class] controller controller to start from
135
+ # @param [Array] args arguments passed to the block
136
+ # @param [Object] default default value to return if no value is found
137
+ # @param [Proc] block block to call with controller and args
138
+ def value_from_parents(controller, *args, default: nil, &block)
139
+ return default if controller == ActionController::Base || controller == AbstractController::Base || controller.nil?
140
+
141
+ thing = yield(controller, *args)
142
+ thing || value_from_parents(controller.superclass, *args, default: default, &block)
143
+ end
144
+
145
+ def set_controller_versions(controller, versions)
146
+ @controller_versions[controller.to_s] = versions
147
+ end
148
+
149
+ def add_param_group(controller, name, &block)
150
+ key = "#{controller.name}##{name}"
151
+ @param_groups[key] = block
152
+ end
153
+
154
+ def get_param_group(controller, name)
155
+ key = "#{controller.name}##{name}"
156
+ if @param_groups.key?(key)
157
+ return @param_groups[key]
158
+ else
159
+ raise "param group #{key} not defined"
160
+ end
161
+ end
162
+
163
+ # get api for given method
164
+ #
165
+ # There are two ways how this method can be used:
166
+ # 1) Specify both parameters
167
+ # resource_id:
168
+ # controller class - UsersController
169
+ # string with resource name (plural) and version - "v1#users"
170
+ # method_name: name of the method (string or symbol)
171
+ #
172
+ # 2) Specify only first parameter:
173
+ # resource_id: string containing both resource and method name joined
174
+ # with '#' symbol.
175
+ # - "users#create" get default version
176
+ # - "v2#users#create" get specific version
177
+ def get_method_description(resource_id, method_name = nil)
178
+ if resource_id.is_a?(String)
179
+ crumbs = resource_id.split('#')
180
+ if method_name.nil?
181
+ method_name = crumbs.pop
182
+ end
183
+ resource_id = crumbs.join("#")
184
+ resource_description = get_resource_description(resource_id)
185
+ elsif resource_id.respond_to? :apipie_resource_descriptions
186
+ resource_description = get_resource_description(resource_id)
187
+ else
188
+ raise ArgumentError.new("Resource #{resource_id} does not exists.")
189
+ end
190
+ resource_description&.method_description(method_name.to_sym)
191
+ end
192
+ alias [] get_method_description
193
+
194
+ # options:
195
+ # => "users"
196
+ # => "v2#users"
197
+ # => V2::UsersController
198
+ def get_resource_description(resource, version = nil)
199
+ if resource.is_a?(String)
200
+ crumbs = resource.split('#')
201
+ if crumbs.size == 2
202
+ version = crumbs.first
203
+ end
204
+ version ||= Apipie.configuration.default_version
205
+ if @resource_descriptions.key?(version)
206
+ return @resource_descriptions[version][crumbs.last]
207
+ end
208
+ else
209
+ resource_id = get_resource_id(resource)
210
+ if version
211
+ resource_id = "#{version}##{resource_id}"
212
+ end
213
+
214
+ if resource_id.nil?
215
+ return nil
216
+ end
217
+ resource_description = get_resource_description(resource_id)
218
+ if resource_description && resource_description.controller.to_s == resource.to_s
219
+ return resource_description
220
+ end
221
+ end
222
+ end
223
+
224
+ # get all versions of resource description
225
+ def get_resource_descriptions(resource)
226
+ available_versions.map do |version|
227
+ get_resource_description(resource, version)
228
+ end.compact
229
+ end
230
+
231
+ # get all versions of method description
232
+ def get_method_descriptions(resource, method)
233
+ get_resource_descriptions(resource).map do |resource_description|
234
+ resource_description.method_description(method.to_sym)
235
+ end.compact
236
+ end
237
+
238
+ def remove_method_description(resource, versions, method_name)
239
+ versions.each do |version|
240
+ resource = get_resource_id(resource)
241
+ if resource_description = get_resource_description("#{version}##{resource}")
242
+ resource_description.remove_method_description(method_name)
243
+ end
244
+ end
245
+ end
246
+
247
+ # initialize variables for gathering dsl data
248
+ def init_env
249
+ @resource_descriptions = ActiveSupport::HashWithIndifferentAccess.new { |h, version| h[version] = {} }
250
+ @controller_to_resource_id = {}
251
+ @param_groups = {}
252
+
253
+ # what versions does the controller belong in (specified by resource_description)?
254
+ @controller_versions = Hash.new { |h, controller| h[controller.to_s] = [] }
255
+ end
256
+
257
+ def recorded_examples
258
+ return @recorded_examples if @recorded_examples
259
+ @recorded_examples = Apipie::Extractor::Writer.load_recorded_examples
260
+ end
261
+
262
+ def reload_examples
263
+ @recorded_examples = nil
264
+ end
265
+
266
+ def json_schema_for_method_response(version, controller_name, method_name, return_code, allow_nulls)
267
+ method = @resource_descriptions[version][controller_name].method_description(method_name)
268
+ raise NoDocumentedMethod.new(controller_name, method_name) if method.nil?
269
+
270
+ Apipie::SwaggerGenerator
271
+ .json_schema_for_method_response(method, return_code, allow_nulls)
272
+ end
273
+
274
+ delegate :json_schema_for_self_describing_class, to: :'Apipie::SwaggerGenerator'
275
+
276
+ def to_swagger_json(version, resource_id, method_name, language, clear_warnings = false)
277
+ return unless valid_search_args?(version, resource_id, method_name)
278
+
279
+ resources =
280
+ Apipie::Generator::Swagger::ResourceDescriptionsCollection
281
+ .new(resource_descriptions)
282
+ .filter(
283
+ resource_id: resource_id,
284
+ method_name: method_name,
285
+ version: version
286
+ )
287
+
288
+ Apipie::SwaggerGenerator.generate_from_resources(
289
+ resources,
290
+ version: version,
291
+ language: language,
292
+ clear_warnings: clear_warnings
293
+ )
294
+ end
295
+
296
+ def to_json(version, resource_id, method_name, lang)
297
+
298
+ return unless valid_search_args?(version, resource_id, method_name)
299
+
300
+ _resources = if resource_id.blank?
301
+ # take just resources which have some methods because
302
+ # we dont want to show eg ApplicationController as resource
303
+ resource_descriptions[version].inject({}) do |result, (k,v)|
304
+ result[k] = v.to_json(nil, lang) unless v._methods.blank?
305
+ result
306
+ end
307
+ else
308
+ [@resource_descriptions[version][resource_id].to_json(method_name, lang)]
309
+ end
310
+
311
+ url_args = Apipie.configuration.version_in_url ? version : ''
312
+
313
+ {
314
+ :docs => {
315
+ :name => Apipie.configuration.app_name,
316
+ :info => Apipie.app_info(version, lang),
317
+ :copyright => Apipie.configuration.copyright,
318
+ :doc_url => Apipie.full_url(url_args),
319
+ :api_url => Apipie.api_base_url(version),
320
+ :resources => _resources
321
+ }
322
+ }
323
+ end
324
+
325
+ def api_controllers_paths
326
+ Dir.glob(Apipie.configuration.api_controllers_matcher)
327
+ end
328
+
329
+ def reload_documentation
330
+ # don't load translated strings, we'll translate them later
331
+ old_locale = locale
332
+ locale = Apipie.configuration.default_locale
333
+
334
+ rails_mark_classes_for_reload
335
+
336
+ api_controllers_paths.each do |f|
337
+ load_controller_from_file f
338
+ end
339
+ @checksum = nil if Apipie.configuration.update_checksum
340
+
341
+ locale = old_locale
342
+ end
343
+
344
+ def load_documentation
345
+ if !@documentation_loaded || Apipie.configuration.reload_controllers?
346
+ Apipie.reload_documentation
347
+ @documentation_loaded = true
348
+ end
349
+ end
350
+
351
+ def compute_checksum
352
+ if Apipie.configuration.use_cache?
353
+ file_base = File.join(Apipie.configuration.cache_dir, Apipie.configuration.doc_base_url)
354
+ all_docs = {}
355
+ Dir.glob(file_base + '/*.json').sort.each do |f|
356
+ all_docs[File.basename(f, '.json')] = JSON.parse(File.read(f))
357
+ end
358
+ else
359
+ load_documentation if available_versions == []
360
+ all_docs = Apipie.available_versions.inject({}) do |all, version|
361
+ all.update(version => Apipie.to_json(version))
362
+ end
363
+ end
364
+ Digest::SHA1.hexdigest(JSON.dump(all_docs))
365
+ end
366
+
367
+ def checksum
368
+ @checksum ||= compute_checksum
369
+ end
370
+
371
+ # Is there a reason to interpret the DSL for this run?
372
+ # with specific setting for some environment there is no reason the dsl
373
+ # should be interpreted (e.g. no validations and doc from cache)
374
+ def active_dsl?
375
+ Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
376
+ end
377
+
378
+ # @deprecated Use {#get_resource_id} instead
379
+ def get_resource_name(klass)
380
+ ActiveSupport::Deprecation.warn(
381
+ <<~HEREDOC
382
+ Apipie::Application.get_resource_name is deprecated.
383
+ Use `Apipie::Application.get_resource_id instead.
384
+ HEREDOC
385
+ )
386
+
387
+ get_resource_id(klass)
388
+ end
389
+
390
+ def set_resource_id(controller, resource_id)
391
+ @controller_to_resource_id[controller] = resource_id
392
+ end
393
+
394
+ def get_resource_id(klass)
395
+ if klass.class == String
396
+ klass
397
+ elsif @controller_to_resource_id.key?(klass)
398
+ @controller_to_resource_id[klass]
399
+ elsif Apipie.configuration.namespaced_resources? && klass.respond_to?(:controller_path)
400
+ return nil if klass == ActionController::Base
401
+
402
+ version_prefix = version_prefix(klass)
403
+ path = klass.controller_path
404
+
405
+ unless version_prefix == '/'
406
+ path =
407
+ path.gsub(version_prefix, '')
408
+ end
409
+
410
+ path.gsub('/', '-')
411
+ elsif klass.respond_to?(:controller_name)
412
+ return nil if klass == ActionController::Base
413
+ klass.controller_name
414
+ else
415
+ raise "Apipie: Can not resolve resource #{klass} name."
416
+ end
417
+ end
418
+
419
+ def locale
420
+ Apipie.configuration.locale&.call(nil)
421
+ end
422
+
423
+ def locale=(locale)
424
+ Apipie.configuration.locale&.call(locale)
425
+ end
426
+
427
+ def translate(str, locale)
428
+ if Apipie.configuration.translate
429
+ Apipie.configuration.translate.call(str, locale)
430
+ else
431
+ str
432
+ end
433
+ end
434
+
435
+ private
436
+
437
+ # Make sure that the version/resource_id/method_name are valid combination
438
+ # resource_id and method_name can be nil
439
+ def valid_search_args?(version, resource_id, method_name)
440
+ return false unless self.resource_descriptions.key?(version)
441
+ if resource_id
442
+ return false unless self.resource_descriptions[version].key?(resource_id)
443
+ if method_name
444
+ resource_description = self.resource_descriptions[version][resource_id]
445
+ return false unless resource_description.valid_method_name?(method_name)
446
+ end
447
+ end
448
+ return true
449
+ end
450
+
451
+ def version_prefix(klass)
452
+ version = controller_versions(klass).first
453
+ base_url = get_base_url(version)
454
+ return "/" if base_url.blank?
455
+ base_url[1..-1] + "/"
456
+ end
457
+
458
+ def get_base_url(version)
459
+ Apipie.configuration.api_base_url[version]
460
+ end
461
+
462
+ def get_resource_version(resource_description)
463
+ if resource_description.respond_to? :_version
464
+ resource_description._version
465
+ else
466
+ Apipie.configuration.default_version
467
+ end
468
+ end
469
+
470
+ def load_controller_from_file(controller_file)
471
+ require_dependency controller_file
472
+ end
473
+
474
+ def ignored?(controller, method = nil)
475
+ ignored = Apipie.configuration.ignored
476
+ return true if ignored.include?(controller.name)
477
+ return true if ignored.include?("#{controller.name}##{method}")
478
+ end
479
+
480
+ # Since Rails 3.2, the classes are reloaded only on file change.
481
+ # We need to reload all the controller classes to rebuild the
482
+ # docs, therefore we just force to reload all the code. This
483
+ # happens only when reload_controllers is set to true and only
484
+ # when showing the documentation.
485
+ #
486
+ # If cache_classes is set to false, it does nothing,
487
+ # as this would break loading of the controllers.
488
+ def rails_mark_classes_for_reload
489
+ unless Rails.application.config.cache_classes
490
+ clear_cached_routes!
491
+ Rails.application.reloader.reload!
492
+ init_env
493
+ reload_examples
494
+ Rails.application.reloader.prepare!
495
+ end
496
+ end
497
+
498
+ end
499
+ end
@@ -0,0 +1,196 @@
1
+ module Apipie
2
+ class Configuration
3
+ extend Forwardable
4
+
5
+ attr_accessor :app_name, :app_info, :copyright, :compress_examples,
6
+ :markup, :disqus_shortname,
7
+ :api_base_url, :doc_base_url, :required_by_default, :layout,
8
+ :default_version, :debug, :version_in_url, :namespaced_resources,
9
+ :validate, :validate_value, :validate_presence, :validate_key, :action_on_non_validated_keys, :authenticate, :doc_path,
10
+ :show_all_examples, :process_params, :update_checksum, :checksum_path,
11
+ :link_extension, :record, :languages, :translate, :locale, :default_locale,
12
+ :persist_show_in_doc, :authorize, :ignore_allow_blank_false
13
+
14
+ def_delegators :swagger, *Apipie::Generator::Swagger::Config.deprecated_methods
15
+
16
+ def swagger
17
+ Apipie::Generator::Swagger::Config.instance
18
+ end
19
+
20
+ def generator
21
+ Apipie::Generator::Config.instance
22
+ end
23
+
24
+ alias validate? validate
25
+ alias required_by_default? required_by_default
26
+ alias namespaced_resources? namespaced_resources
27
+
28
+ # matcher to be used in Dir.glob to find controllers to be reloaded e.g.
29
+ #
30
+ # "#{Rails.root}/app/controllers/api/*.rb"
31
+ attr_accessor :api_controllers_matcher
32
+
33
+ # An object that responds to a `.call(controller)` method responsible for
34
+ # matching the correct controller action
35
+ attr_reader :api_action_matcher
36
+
37
+ def api_action_matcher=(callable)
38
+ raise 'Must implement .call method' unless callable.respond_to?(:call)
39
+
40
+ @api_action_matcher = callable
41
+ end
42
+
43
+ # set to true if you want to reload the controllers at each refresh of the
44
+ # documentation. It requires +:api_controllers_matcher+ to be set to work
45
+ # properly.
46
+ attr_writer :reload_controllers
47
+
48
+ # specify routes if used router differ from default e.g.
49
+ #
50
+ # Api::Engine.routes
51
+ attr_accessor :api_routes
52
+
53
+ # a object responsible for transforming the routes loaded from Rails to a form
54
+ # to be used in the documentation, when using the `api!` keyword. By default,
55
+ # it's Apipie::RoutesFormatter. To customize the behaviour, one can inherit from
56
+ # from this class and override the methods as needed.
57
+ attr_accessor :routes_formatter
58
+
59
+ def reload_controllers?
60
+ @reload_controllers = Rails.env.development? unless defined? @reload_controllers
61
+
62
+ @reload_controllers && @api_controllers_matcher
63
+ end
64
+
65
+ def validate_value
66
+ validate? && @validate_value
67
+ end
68
+ alias validate_value? validate_value
69
+
70
+ def validate_presence
71
+ validate? && @validate_presence
72
+ end
73
+ alias validate_presence? validate_presence
74
+
75
+ def validate_key
76
+ validate? && @validate_key
77
+ end
78
+ alias validate_key? validate_key
79
+
80
+ def process_value?
81
+ @process_params
82
+ end
83
+ # set to true if you want to use pregenerated documentation cache and avoid
84
+ # generating the documentation on runtime (useful for production
85
+ # environment).
86
+ # You can generate the cache by running
87
+ #
88
+ # rake apipie:cache
89
+ attr_accessor :use_cache
90
+ alias use_cache? use_cache
91
+
92
+ attr_writer :cache_dir
93
+ def cache_dir
94
+ @cache_dir ||= File.join(Rails.root, "public", "apipie-cache")
95
+ end
96
+
97
+ # if there is not obvious reason why the DSL should be turned on (no
98
+ # validations, cache turned on etc.), it's disabled to avoid unneeded
99
+ # allocation. It you need the DSL for other reasons, you can force the
100
+ # activation.
101
+ attr_writer :force_dsl
102
+ def force_dsl?
103
+ @force_dsl
104
+ end
105
+
106
+ # array of controller names (strings) (might include actions as well)
107
+ # to be ignored # when extracting description form calls.
108
+ # e.g. %w[Api::CommentsController Api::PostsController#post]
109
+ attr_writer :ignored_by_recorder
110
+ def ignored_by_recorder
111
+ @ignored_by_recorder ||= []
112
+ @ignored_by_recorder.map(&:to_s)
113
+ end
114
+
115
+ # array of controller names (strings) (might include actions as well)
116
+ # to be ignored # when generating the documentation
117
+ # e.g. %w[Api::CommentsController Api::PostsController#post]
118
+ attr_writer :ignored
119
+ def ignored
120
+ @ignored ||= []
121
+ @ignored.map(&:to_s)
122
+ end
123
+
124
+ # Persist the show_in_doc value in the examples if true. Use this if you
125
+ # cannot set the flag in the tests themselves (no rspec for example).
126
+ attr_writer :persist_show_in_doc
127
+
128
+ # comment to put before docs that was generated automatically. It's used to
129
+ # determine if the description should be overwritten next recording.
130
+ # If you want to keep the documentation (prevent from overriding), remove
131
+ # the line above the docs.
132
+ attr_writer :generated_doc_disclaimer
133
+ def generated_doc_disclaimer
134
+ @generated_doc_disclaimer ||= "# DOC GENERATED AUTOMATICALLY: REMOVE THIS LINE TO PREVENT REGENERATING NEXT TIME"
135
+ end
136
+
137
+ def use_disqus?
138
+ !@disqus_shortname.blank?
139
+ end
140
+
141
+ # set app description for default version
142
+ # to maintain backward compatibility
143
+ # new way: config.app_info[version] = description
144
+ def app_info=(description)
145
+ version = Apipie.configuration.default_version
146
+ @app_info[version] = description
147
+ end
148
+
149
+ # set base url for default version of API
150
+ # to set it for specific version use
151
+ # config.api_base_url[version] = url
152
+ def api_base_url=(url)
153
+ version = Apipie.configuration.default_version
154
+ @api_base_url[version] = url
155
+ end
156
+
157
+ def api_routes
158
+ @api_routes || Rails.application.routes
159
+ end
160
+
161
+ def initialize
162
+ @markup = Apipie::Markup::RDoc.new
163
+ @app_name = "Another API"
164
+ @app_info = ActiveSupport::HashWithIndifferentAccess.new
165
+ @copyright = nil
166
+ @validate = :implicitly
167
+ @validate_value = true
168
+ @validate_presence = true
169
+ @validate_key = false
170
+ @action_on_non_validated_keys = :raise
171
+ @required_by_default = false
172
+ @api_base_url = ActiveSupport::HashWithIndifferentAccess.new
173
+ @api_action_matcher = proc { |controller| controller.params[:action] }
174
+ @doc_base_url = "/apipie"
175
+ @layout = "apipie/apipie"
176
+ @disqus_shortname = nil
177
+ @default_version = "1.0"
178
+ @debug = false
179
+ @ignore_allow_blank_false = false
180
+ @version_in_url = true
181
+ @namespaced_resources = false
182
+ @doc_path = "doc"
183
+ @process_params = false
184
+ @checksum_path = [@doc_base_url, '/api/']
185
+ @update_checksum = false
186
+ @link_extension = ".html"
187
+ @record = false
188
+ @languages = []
189
+ @default_locale = 'en'
190
+ @locale = lambda { |locale| @default_locale }
191
+ @translate = lambda { |str, locale| str }
192
+ @persist_show_in_doc = false
193
+ @routes_formatter = RoutesFormatter.new
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,9 @@
1
+ module Apipie
2
+ module BaseUrlExtension
3
+ attr_accessor :base_url
4
+ end
5
+ end
6
+
7
+ class ActionDispatch::Journey::Route
8
+ include Apipie::BaseUrlExtension
9
+ end