praxis 0.16.1 → 0.17.0

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 (399) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +41 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/lib/api_browser/Gruntfile.js +20 -4
  8. data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +6 -6
  9. data/lib/api_browser/app/bower_components/angular-mocks/README.md +11 -5
  10. data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +475 -216
  11. data/lib/api_browser/app/bower_components/angular-mocks/bower.json +2 -2
  12. data/lib/api_browser/app/bower_components/angular-mocks/ngAnimateMock.js +2 -0
  13. data/lib/api_browser/app/bower_components/angular-mocks/ngMock.js +2 -0
  14. data/lib/api_browser/app/bower_components/angular-mocks/ngMockE2E.js +2 -0
  15. data/lib/api_browser/app/bower_components/angular-mocks/package.json +1 -1
  16. data/lib/api_browser/app/bower_components/angular-sanitize/.bower.json +8 -8
  17. data/lib/api_browser/app/bower_components/angular-sanitize/README.md +19 -5
  18. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.js +186 -127
  19. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js +12 -10
  20. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js.map +3 -3
  21. data/lib/api_browser/app/bower_components/angular-sanitize/bower.json +3 -2
  22. data/lib/api_browser/app/bower_components/angular-sanitize/index.js +2 -0
  23. data/lib/api_browser/app/bower_components/angular-sanitize/package.json +26 -0
  24. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/.bower.json +15 -8
  25. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/bower.json +11 -3
  26. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-csp.css +6 -0
  27. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js +1177 -453
  28. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js +4 -4
  29. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.js +1066 -404
  30. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.min.js +3 -3
  31. data/lib/api_browser/app/bower_components/angular-ui-router/.bower.json +5 -6
  32. data/lib/api_browser/app/bower_components/angular-ui-router/CHANGELOG.md +208 -3
  33. data/lib/api_browser/app/bower_components/angular-ui-router/CONTRIBUTING.md +65 -0
  34. data/lib/api_browser/app/bower_components/angular-ui-router/LICENSE +1 -1
  35. data/lib/api_browser/app/bower_components/angular-ui-router/README.md +36 -71
  36. data/lib/api_browser/app/bower_components/angular-ui-router/api/angular-ui-router.d.ts +126 -0
  37. data/lib/api_browser/app/bower_components/angular-ui-router/bower.json +1 -1
  38. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.js +1902 -755
  39. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.min.js +2 -2
  40. data/lib/api_browser/app/bower_components/angular-ui-router/src/common.js +69 -23
  41. data/lib/api_browser/app/bower_components/angular-ui-router/src/resolve.js +15 -5
  42. data/lib/api_browser/app/bower_components/angular-ui-router/src/state.js +556 -295
  43. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateDirectives.js +101 -42
  44. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateFilters.js +6 -2
  45. data/lib/api_browser/app/bower_components/angular-ui-router/src/templateFactory.js +2 -2
  46. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlMatcherFactory.js +822 -97
  47. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlRouter.js +274 -120
  48. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewDirective.js +33 -20
  49. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewScroll.js +1 -1
  50. data/lib/api_browser/app/bower_components/angular/.bower.json +5 -5
  51. data/lib/api_browser/app/bower_components/angular/README.md +2 -5
  52. data/lib/api_browser/app/bower_components/angular/angular-csp.css +5 -8
  53. data/lib/api_browser/app/bower_components/angular/angular.js +12975 -6996
  54. data/lib/api_browser/app/bower_components/angular/angular.min.js +285 -213
  55. data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
  56. data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
  57. data/lib/api_browser/app/bower_components/angular/bower.json +1 -1
  58. data/lib/api_browser/app/bower_components/angular/index.js +2 -0
  59. data/lib/api_browser/app/bower_components/angular/package.json +2 -2
  60. data/lib/api_browser/app/bower_components/bootstrap-sass/.bower.json +31 -16
  61. data/lib/api_browser/app/bower_components/bootstrap-sass/CHANGELOG.md +108 -0
  62. data/lib/api_browser/app/bower_components/bootstrap-sass/CONTRIBUTING.md +55 -37
  63. data/lib/api_browser/app/bower_components/bootstrap-sass/README.md +147 -206
  64. data/lib/api_browser/app/bower_components/bootstrap-sass/bower.json +19 -8
  65. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.eot +0 -0
  66. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.svg +0 -0
  67. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.ttf +0 -0
  68. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.woff +0 -0
  69. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/javascripts/bootstrap.js +12 -0
  70. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/affix.js +1 -1
  71. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/alert.js +1 -1
  72. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/button.js +11 -5
  73. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/carousel.js +5 -5
  74. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/collapse.js +1 -1
  75. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/dropdown.js +5 -5
  76. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/modal.js +1 -1
  77. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/popover.js +1 -1
  78. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/scrollspy.js +2 -2
  79. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tab.js +1 -1
  80. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tooltip.js +1 -1
  81. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/transition.js +1 -1
  82. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/stylesheets/bootstrap.scss +1 -0
  83. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_alerts.scss +0 -0
  84. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_badges.scss +6 -6
  85. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_breadcrumbs.scss +0 -0
  86. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_button-groups.scss +7 -33
  87. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_buttons.scss +2 -5
  88. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_carousel.scss +1 -0
  89. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_close.scss +0 -0
  90. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_code.scss +0 -0
  91. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_component-animations.scss +0 -0
  92. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_dropdowns.scss +3 -8
  93. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_forms.scss +11 -0
  94. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_glyphicons.scss +5 -5
  95. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_grid.scss +12 -26
  96. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_input-groups.scss +1 -1
  97. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_jumbotron.scss +8 -2
  98. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_labels.scss +6 -0
  99. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_list-group.scss +0 -0
  100. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_media.scss +0 -0
  101. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_mixins.scss +38 -51
  102. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_modals.scss +2 -5
  103. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navbar.scss +41 -53
  104. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navs.scss +0 -20
  105. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_normalize.scss +0 -0
  106. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pager.scss +0 -0
  107. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pagination.scss +0 -0
  108. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_panels.scss +11 -1
  109. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_popovers.scss +0 -0
  110. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_print.scss +0 -0
  111. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_progress-bars.scss +0 -12
  112. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_responsive-utilities.scss +0 -0
  113. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_scaffolding.scss +0 -0
  114. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tables.scss +5 -18
  115. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_theme.scss +2 -2
  116. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_thumbnails.scss +9 -3
  117. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tooltip.scss +0 -0
  118. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_type.scss +54 -52
  119. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_utilities.scss +0 -0
  120. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_variables.scss +20 -11
  121. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_wells.scss +0 -0
  122. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/bootstrap.scss +0 -0
  123. data/lib/api_browser/app/bower_components/lodash/.bower.json +9 -13
  124. data/lib/api_browser/app/bower_components/lodash/LICENSE.txt +3 -3
  125. data/lib/api_browser/app/bower_components/lodash/bower.json +4 -7
  126. data/lib/api_browser/app/bower_components/lodash/lodash.js +12235 -0
  127. data/lib/api_browser/app/bower_components/lodash/lodash.min.js +98 -0
  128. data/lib/api_browser/app/index.html +0 -1
  129. data/lib/api_browser/app/js/app.js +2 -5
  130. data/lib/api_browser/app/js/controllers/action.js +21 -37
  131. data/lib/api_browser/app/js/controllers/controller.js +23 -1
  132. data/lib/api_browser/app/js/controllers/menu.js +46 -14
  133. data/lib/api_browser/app/js/controllers/type.js +2 -9
  134. data/lib/api_browser/app/js/directives/attribute_description.js +15 -5
  135. data/lib/api_browser/app/js/directives/attribute_table.js +6 -6
  136. data/lib/api_browser/app/js/directives/fixed_if_fits.js +20 -0
  137. data/lib/api_browser/app/js/directives/no_container.js +6 -6
  138. data/lib/api_browser/app/js/directives/type_placeholder.js +21 -0
  139. data/lib/api_browser/app/js/factories/Configuration.js +13 -0
  140. data/lib/api_browser/app/js/factories/Documentation.js +0 -3
  141. data/lib/api_browser/app/js/factories/normalize_attributes.js +19 -0
  142. data/lib/api_browser/app/js/factories/template_for.js +113 -0
  143. data/lib/api_browser/app/sass/modules/_body.scss +26 -4
  144. data/lib/api_browser/app/sass/modules/_sidebar.scss +68 -1
  145. data/lib/api_browser/app/sass/praxis.scss +1 -5
  146. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +13 -4
  147. data/lib/api_browser/app/views/action.html +13 -17
  148. data/lib/api_browser/app/views/controller.html +32 -4
  149. data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
  150. data/lib/api_browser/app/views/directives/attribute_description/{_default.html → default.html} +0 -0
  151. data/lib/api_browser/app/views/directives/attribute_description/example.html +13 -0
  152. data/lib/api_browser/app/views/directives/attribute_description/headers.html +8 -0
  153. data/lib/api_browser/app/views/directives/attribute_description/member_options.html +4 -0
  154. data/lib/api_browser/app/views/directives/attribute_description/values.html +14 -0
  155. data/lib/api_browser/app/views/directives/attribute_table.html +2 -2
  156. data/lib/api_browser/app/views/home.html +1 -3
  157. data/lib/api_browser/app/views/layout.html +3 -36
  158. data/lib/api_browser/app/views/menu.html +45 -0
  159. data/lib/api_browser/app/views/navbar.html +1 -1
  160. data/lib/api_browser/app/views/type.html +2 -2
  161. data/lib/api_browser/app/views/type/{_details.html → details.html} +6 -6
  162. data/lib/api_browser/app/views/types/embedded/default.html +10 -0
  163. data/lib/api_browser/app/views/types/embedded/links.html +11 -0
  164. data/lib/api_browser/app/views/types/embedded/struct.html +2 -0
  165. data/lib/api_browser/app/views/types/label/link.html +1 -0
  166. data/lib/api_browser/app/views/types/label/primitive.html +1 -0
  167. data/lib/api_browser/app/views/types/label/primitive_collection.html +1 -0
  168. data/lib/api_browser/app/views/types/label/type.html +1 -0
  169. data/lib/api_browser/app/views/types/label/type_collection.html +1 -0
  170. data/lib/api_browser/app/views/{directives/request_body/_default.html → types/standalone/default.html} +1 -1
  171. data/lib/api_browser/app/views/types/standalone/struct.html +1 -0
  172. data/lib/api_browser/bower.json +9 -9
  173. data/lib/api_browser/package.json +1 -1
  174. data/lib/praxis.rb +10 -4
  175. data/lib/praxis/action_definition.rb +16 -4
  176. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -2
  177. data/lib/praxis/api_definition.rb +3 -1
  178. data/lib/praxis/api_general_info.rb +49 -5
  179. data/lib/praxis/application.rb +12 -4
  180. data/lib/praxis/bootloader.rb +1 -0
  181. data/lib/praxis/bootloader_stages/environment.rb +2 -0
  182. data/lib/praxis/bootloader_stages/routing.rb +1 -1
  183. data/lib/praxis/bootloader_stages/subgroup_loader.rb +1 -0
  184. data/lib/praxis/exceptions/validation.rb +7 -0
  185. data/lib/praxis/handlers/plain.rb +16 -0
  186. data/lib/praxis/handlers/xml.rb +4 -4
  187. data/lib/praxis/links.rb +13 -3
  188. data/lib/praxis/media_type_identifier.rb +3 -0
  189. data/lib/praxis/multipart/parser.rb +41 -48
  190. data/lib/praxis/multipart/part.rb +196 -3
  191. data/lib/praxis/request.rb +14 -11
  192. data/lib/praxis/request_stages/request_stage.rb +4 -0
  193. data/lib/praxis/request_stages/response.rb +10 -9
  194. data/lib/praxis/request_stages/validate.rb +1 -7
  195. data/lib/praxis/request_stages/validate_params_and_headers.rb +30 -5
  196. data/lib/praxis/request_stages/validate_payload.rb +14 -5
  197. data/lib/praxis/resource_definition.rb +117 -15
  198. data/lib/praxis/response.rb +6 -5
  199. data/lib/praxis/response_definition.rb +51 -5
  200. data/lib/praxis/responses/http.rb +5 -0
  201. data/lib/praxis/responses/multipart_ok.rb +51 -0
  202. data/lib/praxis/responses/validation_error.rb +7 -7
  203. data/lib/praxis/restful_doc_generator.rb +9 -4
  204. data/lib/praxis/route.rb +3 -2
  205. data/lib/praxis/router.rb +26 -16
  206. data/lib/praxis/router/rack.rb +51 -0
  207. data/lib/praxis/router/simple.rb +146 -0
  208. data/lib/praxis/routing_config.rb +2 -2
  209. data/lib/praxis/trait.rb +1 -1
  210. data/lib/praxis/types/fuzzy_hash.rb +49 -0
  211. data/lib/praxis/types/media_type_common.rb +1 -1
  212. data/lib/praxis/types/multipart.rb +47 -12
  213. data/lib/praxis/types/multipart_array.rb +320 -0
  214. data/lib/praxis/types/multipart_array/part_definition.rb +52 -0
  215. data/lib/praxis/validation_handler.rb +10 -0
  216. data/lib/praxis/version.rb +2 -2
  217. data/praxis.gemspec +3 -3
  218. data/spec/api_browser/directives/type_placeholder_spec.js +134 -0
  219. data/spec/api_browser/factories/normalize_attributes_spec.js +97 -0
  220. data/spec/api_browser/factories/template_for_spec.js +67 -0
  221. data/spec/functional_spec.rb +111 -45
  222. data/spec/praxis/action_definition_spec.rb +31 -7
  223. data/spec/praxis/api_definition_spec.rb +2 -2
  224. data/spec/praxis/api_general_info_spec.rb +25 -0
  225. data/spec/praxis/application_spec.rb +24 -11
  226. data/spec/praxis/handlers/xml_spec.rb +55 -33
  227. data/spec/praxis/links_spec.rb +18 -1
  228. data/spec/praxis/media_type_collection_spec.rb +1 -1
  229. data/spec/praxis/media_type_spec.rb +2 -2
  230. data/spec/praxis/multipart/parser_spec.rb +21 -13
  231. data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +1 -1
  232. data/spec/praxis/request_spec.rb +52 -24
  233. data/spec/praxis/{request_stages_action_spec.rb → request_stages/action_spec.rb} +1 -1
  234. data/spec/praxis/{request_stage_spec.rb → request_stages/request_stage_spec.rb} +0 -0
  235. data/spec/praxis/{request_stages_validate_spec.rb → request_stages/validate_spec.rb} +1 -1
  236. data/spec/praxis/resource_definition_spec.rb +30 -4
  237. data/spec/praxis/response_definition_spec.rb +60 -19
  238. data/spec/praxis/response_spec.rb +2 -2
  239. data/spec/praxis/responses/validation_error_spec.rb +33 -16
  240. data/spec/praxis/route_spec.rb +4 -2
  241. data/spec/praxis/router_spec.rb +28 -12
  242. data/spec/praxis/routing_config_spec.rb +11 -5
  243. data/spec/praxis/types/collection_spec.rb +1 -1
  244. data/spec/praxis/types/fuzzy_hash_spec.rb +20 -0
  245. data/spec/praxis/types/multipart_array/part_definition_spec.rb +5 -0
  246. data/spec/praxis/types/multipart_array_spec.rb +334 -0
  247. data/spec/praxis/types/multipart_spec.rb +14 -5
  248. data/spec/spec_app/app/controllers/instances.rb +20 -10
  249. data/spec/spec_app/app/controllers/volumes.rb +8 -4
  250. data/spec/spec_app/app/responses/bulk_response.rb +0 -6
  251. data/spec/spec_app/config/environment.rb +13 -0
  252. data/spec/spec_app/design/api.rb +7 -10
  253. data/spec/spec_app/design/media_types/instance.rb +3 -1
  254. data/spec/spec_app/design/resources/instances.rb +50 -41
  255. data/spec/spec_app/design/resources/volume_snapshots.rb +39 -0
  256. data/spec/spec_app/design/resources/volumes.rb +11 -6
  257. data/spec/spec_helper.rb +3 -1
  258. metadata +125 -218
  259. data/lib/api_browser/app/bower_components/angular-ui-router/src/compat.js +0 -146
  260. data/lib/api_browser/app/bower_components/bootstrap-sass/CNAME +0 -1
  261. data/lib/api_browser/app/bower_components/bootstrap-sass/DOCS-LICENSE +0 -319
  262. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile +0 -5
  263. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile.lock +0 -14
  264. data/lib/api_browser/app/bower_components/bootstrap-sass/Gruntfile.js +0 -244
  265. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE +0 -176
  266. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE-MIT +0 -21
  267. data/lib/api_browser/app/bower_components/bootstrap-sass/Rakefile +0 -44
  268. data/lib/api_browser/app/bower_components/bootstrap-sass/_config.yml +0 -25
  269. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/ads.html +0 -1
  270. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/footer.html +0 -34
  271. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/header.html +0 -42
  272. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-about.html +0 -12
  273. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-components.html +0 -137
  274. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-css.html +0 -99
  275. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-customize.html +0 -40
  276. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-getting-started.html +0 -44
  277. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-javascript.html +0 -88
  278. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-main.html +0 -37
  279. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/old-bs-docs.html +0 -8
  280. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/social-buttons.html +0 -16
  281. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/default.html +0 -79
  282. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/home.html +0 -47
  283. data/lib/api_browser/app/bower_components/bootstrap-sass/about.html +0 -93
  284. data/lib/api_browser/app/bower_components/bootstrap-sass/browserstack.json +0 -37
  285. data/lib/api_browser/app/bower_components/bootstrap-sass/components.html +0 -3689
  286. data/lib/api_browser/app/bower_components/bootstrap-sass/composer.json +0 -28
  287. data/lib/api_browser/app/bower_components/bootstrap-sass/css.html +0 -2674
  288. data/lib/api_browser/app/bower_components/bootstrap-sass/customize.html +0 -1715
  289. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.css +0 -427
  290. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.min.css +0 -1
  291. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.css +0 -6350
  292. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.min.css +0 -1
  293. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.js +0 -2002
  294. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.min.js +0 -9
  295. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/docs.css +0 -1195
  296. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/pygments-manni.css +0 -66
  297. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  298. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/favicon.png +0 -0
  299. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/application.js +0 -103
  300. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/customizer.js +0 -332
  301. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/filesaver.js +0 -169
  302. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/holder.js +0 -404
  303. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/ie8-responsive-file-warning.js +0 -12
  304. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/jszip.js +0 -1467
  305. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/less.js +0 -9
  306. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/raw-files.js +0 -3
  307. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/uglify.js +0 -14
  308. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/carousel.css +0 -148
  309. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/index.html +0 -206
  310. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/grid.css +0 -28
  311. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/index.html +0 -148
  312. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/index.html +0 -82
  313. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/jumbotron-narrow.css +0 -79
  314. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/index.html +0 -99
  315. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/jumbotron.css +0 -5
  316. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/index.html +0 -83
  317. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/justified-nav.css +0 -88
  318. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/index.html +0 -91
  319. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/navbar-fixed-top.css +0 -4
  320. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/index.html +0 -92
  321. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/navbar-static-top.css +0 -7
  322. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/index.html +0 -88
  323. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/navbar.css +0 -8
  324. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/index.html +0 -101
  325. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/non-responsive.css +0 -116
  326. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/index.html +0 -130
  327. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.css +0 -50
  328. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.js +0 -5
  329. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/carousel.jpg +0 -0
  330. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/grid.jpg +0 -0
  331. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron-narrow.jpg +0 -0
  332. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron.jpg +0 -0
  333. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/justified-nav.jpg +0 -0
  334. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-fixed.jpg +0 -0
  335. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-static.jpg +0 -0
  336. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar.jpg +0 -0
  337. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/non-responsive.jpg +0 -0
  338. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/offcanvas.jpg +0 -0
  339. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sign-in.jpg +0 -0
  340. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/starter-template.jpg +0 -0
  341. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer-navbar.jpg +0 -0
  342. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer.jpg +0 -0
  343. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/theme.jpg +0 -0
  344. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/index.html +0 -50
  345. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/signin.css +0 -40
  346. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/index.html +0 -68
  347. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/starter-template.css +0 -7
  348. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/index.html +0 -91
  349. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/sticky-footer-navbar.css +0 -45
  350. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/index.html +0 -55
  351. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/sticky-footer.css +0 -38
  352. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/index.html +0 -384
  353. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/theme.css +0 -14
  354. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.eot +0 -0
  355. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.svg +0 -229
  356. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.ttf +0 -0
  357. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.woff +0 -0
  358. data/lib/api_browser/app/bower_components/bootstrap-sass/getting-started.html +0 -1021
  359. data/lib/api_browser/app/bower_components/bootstrap-sass/index.html +0 -16
  360. data/lib/api_browser/app/bower_components/bootstrap-sass/javascript.html +0 -1983
  361. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/index.html +0 -52
  362. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/affix.js +0 -25
  363. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/alert.js +0 -62
  364. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/button.js +0 -116
  365. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/carousel.js +0 -87
  366. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/collapse.js +0 -164
  367. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/dropdown.js +0 -219
  368. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/modal.js +0 -196
  369. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/phantom.js +0 -69
  370. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/popover.js +0 -133
  371. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/scrollspy.js +0 -37
  372. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tab.js +0 -86
  373. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tooltip.js +0 -437
  374. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/transition.js +0 -13
  375. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/jquery.js +0 -6
  376. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.css +0 -232
  377. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.js +0 -1510
  378. data/lib/api_browser/app/bower_components/bootstrap-sass/package.json +0 -40
  379. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.js +0 -7157
  380. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.min.js +0 -61
  381. data/lib/api_browser/app/bower_components/lodash/dist/lodash.js +0 -6785
  382. data/lib/api_browser/app/bower_components/lodash/dist/lodash.min.js +0 -56
  383. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.js +0 -4979
  384. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.min.js +0 -39
  385. data/lib/api_browser/app/js/directives/attribute_table_row.js +0 -17
  386. data/lib/api_browser/app/js/directives/request_body.js +0 -25
  387. data/lib/api_browser/app/js/directives/request_headers.js +0 -17
  388. data/lib/api_browser/app/js/directives/request_parameters.js +0 -17
  389. data/lib/api_browser/app/js/directives/type_label.js +0 -52
  390. data/lib/api_browser/app/js/factories/PayloadTemplates.js +0 -10
  391. data/lib/api_browser/app/js/factories/TemplateProvider.js +0 -45
  392. data/lib/api_browser/app/js/factories/TypeTemplates.js +0 -11
  393. data/lib/api_browser/app/views/directives/attribute_description/_example.html +0 -13
  394. data/lib/api_browser/app/views/directives/attribute_description/_headers.html +0 -8
  395. data/lib/api_browser/app/views/directives/attribute_table_row/_default.html +0 -10
  396. data/lib/api_browser/app/views/directives/attribute_table_row/_links.html +0 -11
  397. data/lib/api_browser/app/views/directives/attribute_table_row/_struct.html +0 -2
  398. data/lib/api_browser/app/views/directives/request_body/_struct.html +0 -1
  399. data/lib/api_browser/app/views/resource/_actions.html +0 -27
@@ -55,6 +55,15 @@ module Praxis
55
55
  end
56
56
  end
57
57
 
58
+ def example(context=nil)
59
+ return nil if self.media_type.nil?
60
+ return nil if self.media_type.kind_of?(SimpleMediaType)
61
+ if context.nil?
62
+ context = "#{self.media_type.name}-#{self.name}"
63
+ end
64
+ self.media_type.example(context)
65
+ end
66
+
58
67
  def location(loc=nil)
59
68
  return @spec[:location] if loc.nil?
60
69
  unless ( loc.is_a?(Regexp) || loc.is_a?(String) )
@@ -120,6 +129,14 @@ module Praxis
120
129
  media_type.describe(true) # TODO: is a shallow describe what we want? or just the name?
121
130
  end
122
131
  end
132
+
133
+ # Generate an appropriate response example.
134
+ # A rendered response will need to contain not just the body of the associated media_type...
135
+ # but also headers, url...etc...
136
+ #if (media_type_example = self.example)
137
+ # content[:example] = self.media_type.dump( media_type_example )
138
+ #end
139
+
123
140
  unless headers == nil
124
141
  headers.each do |name, value|
125
142
  content[:headers][name] = _describe_header(value)
@@ -137,12 +154,16 @@ module Praxis
137
154
  { :value => data_value, :type => data_type }
138
155
  end
139
156
 
140
- def validate( response )
157
+ def validate(response, validate_body: false)
141
158
  validate_status!(response)
142
159
  validate_location!(response)
143
160
  validate_headers!(response)
144
161
  validate_content_type!(response)
145
162
  validate_parts!(response)
163
+
164
+ if validate_body
165
+ validate_body!(response)
166
+ end
146
167
  end
147
168
 
148
169
  def parts(proc=nil, like: nil, **args, &block)
@@ -227,7 +248,7 @@ module Praxis
227
248
 
228
249
  # Validates Content-Type header and response media type
229
250
  #
230
- # @param [Object] action
251
+ # @param [Object] response
231
252
  #
232
253
  # @raise [Exceptions::Validation] When there is a missing required header
233
254
  #
@@ -245,13 +266,38 @@ module Praxis
245
266
  end
246
267
  end
247
268
 
269
+ # Validates response body
270
+ #
271
+ # @param [Object] response
272
+ #
273
+ # @raise [Exceptions::Validation] When there is a missing required header..
274
+ def validate_body!(response)
275
+ return unless media_type
276
+ return if media_type.kind_of? SimpleMediaType
277
+
278
+ errors = self.media_type.validate(self.media_type.load(response.body))
279
+ if errors.any?
280
+ message = "Invalid response body for #{media_type.identifier}." +
281
+ "Errors: #{errors.inspect}"
282
+ raise Exceptions::Validation.new(message, errors: errors)
283
+ end
284
+
285
+ end
286
+
248
287
  def validate_parts!(response)
249
288
  return unless parts
250
289
 
251
- response.parts.each do |name, part|
252
- parts.validate(part)
290
+ case response.body
291
+ when Praxis::Types::MultipartArray
292
+ response.body.each do |part|
293
+ parts.validate(part)
294
+ end
295
+ else
296
+ # TODO: remove with other Multipart deprecations.
297
+ response.parts.each do |name, part|
298
+ parts.validate(part)
299
+ end
253
300
  end
254
-
255
301
  end
256
302
 
257
303
  end
@@ -18,6 +18,11 @@ module Praxis
18
18
  # being created.
19
19
  class Created < Praxis::Response
20
20
  self.status = 201
21
+
22
+ def initialize(status:self.class.status, headers:{}, body:'', location: nil)
23
+ super(status: status, headers: headers, body: body)
24
+ headers['Location'] = location if location
25
+ end
21
26
  end
22
27
 
23
28
 
@@ -0,0 +1,51 @@
1
+ module Praxis
2
+ module Responses
3
+ class MultipartOk < Ok
4
+
5
+ def initialize(status:self.class.status, headers:{}, body:'')
6
+ @name = response_name
7
+ @status = status
8
+ @headers = headers
9
+ @body = body
10
+ end
11
+
12
+ def handle
13
+ case @body
14
+ when Praxis::Types::MultipartArray
15
+ if @headers['Content-Type'].nil?
16
+ @headers['Content-Type'] = @body.content_type
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ def encode!
23
+ case @body
24
+ when Praxis::Types::MultipartArray
25
+ @body = @body.dump
26
+ else
27
+ super
28
+ end
29
+ end
30
+
31
+ def finish
32
+ format!
33
+ encode!
34
+
35
+ @body = Array(@body)
36
+
37
+ [@status, @headers, @body]
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ ApiDefinition.define do |api|
45
+ api.response_template :multipart_ok do |media_type: Praxis::Types::MultipartArray|
46
+ status 200
47
+ media_type media_type
48
+ end
49
+ end
50
+
51
+ end
@@ -3,20 +3,20 @@ module Praxis
3
3
  module Responses
4
4
 
5
5
  class ValidationError < BadRequest
6
- def initialize(errors: nil, exception: nil, message: nil, **opts)
6
+ def initialize(summary:, errors: nil, exception: nil, **opts)
7
7
  super(**opts)
8
8
  @headers['Content-Type'] = 'application/json' #TODO: might want an error mediatype
9
9
  @errors = errors
10
+ unless @errors # The exception message will the the only error if no errors are passed in
11
+ @errors = [exception.message] if exception && exception.message
12
+ end
10
13
  @exception = exception
11
- @message = message || (exception && exception.message)
14
+ @summary = summary
12
15
  end
13
16
 
14
17
  def format!
15
- if @errors
16
- @body = {name: 'ValidationError', errors: @errors}
17
- elsif @message
18
- @body = {name: 'ValidationError', message: @message}
19
- end
18
+ @body = {name: 'ValidationError', summary: @summary }
19
+ @body[:errors] = @errors if @errors
20
20
 
21
21
  if @exception && @exception.cause
22
22
  @body[:cause] = {name: @exception.cause.class.name, message: @exception.cause.message}
@@ -108,6 +108,10 @@ module Praxis
108
108
  end
109
109
  end
110
110
 
111
+ def parent
112
+ @controller_config.parent
113
+ end
114
+
111
115
  def friendly_name
112
116
  # FIXME: is it really about the controller? or the attached resource definition?
113
117
  segments = self.name.split("::")
@@ -160,7 +164,7 @@ module Praxis
160
164
  def dump_example_for(context_name, object)
161
165
  example = object.example(Array(context_name))
162
166
  if object.is_a? Praxis::Blueprint
163
- example.render(:master)
167
+ example.render(view: :master)
164
168
  elsif object.is_a? Attributor::Attribute
165
169
  object.dump(example)
166
170
  else
@@ -216,7 +220,7 @@ module Praxis
216
220
  type_output[:views].each do |view_name, view_info|
217
221
  # Add and example for each view
218
222
  unless( type < Praxis::Links ) #TODO: why do we need to skip an example for links?
219
- view_info[:example] = example_data.render(view_name)
223
+ view_info[:example] = example_data.render(view: view_name)
220
224
  end
221
225
  end
222
226
  end
@@ -224,7 +228,7 @@ module Praxis
224
228
  # ...but not for links or link classes (there's no object container context if done alone!!)
225
229
  unless( type < Praxis::Links ) #TODO: again, why is this special?
226
230
  type_output[:example] = if example_data.respond_to? :render
227
- example_data.render(:master)
231
+ example_data.render(view: :master)
228
232
  else
229
233
  type.dump(example_data)
230
234
  end
@@ -259,6 +263,7 @@ module Praxis
259
263
  @resources.each do |r|
260
264
  index[r.version] ||= Hash.new
261
265
  info = {controller: r.id, name: r.name}
266
+ info[:parent] = r.parent.controller ? r.parent.controller.id : r.parent.id if r.parent
262
267
  if r.media_type
263
268
  info[:media_type] = r.media_type.id
264
269
  media_types_seen_from_controllers << r.media_type
@@ -275,7 +280,7 @@ module Praxis
275
280
 
276
281
  reportable_types.each do |type|
277
282
  index[version] ||= Hash.new
278
- display_name = type.name.split("::").last + " (*)" #somehow this is just a MT so we probably wanna mark it different
283
+ display_name = type.name.split("::").last
279
284
  if index[version].has_key? display_name
280
285
  raise "Display name already taken for version #{version}! #{display_name}"
281
286
  end
data/lib/praxis/route.rb CHANGED
@@ -1,14 +1,15 @@
1
1
  module Praxis
2
2
 
3
3
  class Route
4
- attr_accessor :verb, :path, :version, :name, :options
4
+ attr_accessor :verb, :path, :version, :name, :prefixed_path, :options
5
5
 
6
- def initialize(verb, path, version='n/a', name:nil, **options)
6
+ def initialize(verb, path, version='n/a', name:nil, prefixed_path:nil, **options)
7
7
  @verb = verb
8
8
  @path = path
9
9
  @version = version
10
10
  @name = name
11
11
  @options = options
12
+ @prefixed_path = prefixed_path
12
13
  end
13
14
 
14
15
  def describe
data/lib/praxis/router.rb CHANGED
@@ -1,9 +1,11 @@
1
- require 'mustermann/router/rack'
1
+ require 'praxis/router/rack'
2
2
 
3
3
  module Praxis
4
4
 
5
5
  class Router
6
- attr_reader :request_class, :application
6
+ attr_reader :request_class
7
+ attr_reader :application
8
+
7
9
 
8
10
  class VersionMatcher
9
11
  def initialize(target, version: 'n/a')
@@ -11,7 +13,7 @@ module Praxis
11
13
  @version = version
12
14
  end
13
15
  def call(request)
14
- if request.version(@target.action.resource_definition.version_options) == @version
16
+ if request.version == @version
15
17
  @target.call(request)
16
18
  else
17
19
  # Version doesn't match, pass and continue
@@ -41,15 +43,23 @@ module Praxis
41
43
 
42
44
  def initialize(application, request_class: Praxis::Request)
43
45
  @routes = Hash.new do |hash, verb|
44
- hash[verb] = RequestRouter.new
46
+ hash[verb] = RequestRouter.new
45
47
  end
46
48
  @request_class = request_class
47
49
  @application = application
48
50
  end
49
51
 
50
52
  def add_route(target, route)
51
- version_wrapper = VersionMatcher.new(target, version: route.version)
52
- @routes[route.verb].on(route.path, call: version_wrapper)
53
+ path_versioning = (Application.instance.versioning_scheme == :path)
54
+
55
+ # DEPRECATED: remove with ResourceDefinition.version using: :path
56
+ path_versioning ||= (target.action.resource_definition.version_options[:using] == :path)
57
+
58
+ unless path_versioning
59
+ target = VersionMatcher.new(target, version: route.version)
60
+ end
61
+
62
+ @routes[route.verb].on(route.path, call: target)
53
63
  end
54
64
 
55
65
  def call(env_or_request)
@@ -67,26 +77,26 @@ module Praxis
67
77
  result = r.call(request) if r
68
78
  # If we didn't have an exact verb route, or if we did but the rest or route conditions didn't match
69
79
  if( r == nil || result == :not_found )
70
- # Fallback to a wildcard router, if there is one registered
80
+ # Fallback to a wildcard router, if there is one registered
71
81
  result = if @routes.key?('ANY')
72
- @routes['ANY'].call(request)
73
- else
74
- :not_found
75
- end
82
+ @routes['ANY'].call(request)
83
+ else
84
+ :not_found
85
+ end
76
86
  end
77
87
 
78
88
  if result == :not_found
79
89
  # no need to try :path as we cannot really know if you've attempted to pass a version through it here
80
90
  # plus we wouldn't have tracked it as unmatched
81
- version = request.version(using: [:header,:params])
91
+ version = request.version
82
92
  attempted_versions = request.unmatched_versions
83
93
  body = "NotFound"
84
94
  unless attempted_versions.empty? || (attempted_versions.size == 1 && attempted_versions.first == 'n/a')
85
95
  body += if version == 'n/a'
86
- ". Your request did not specify an API version.".freeze
87
- else
88
- ". Your request speficied API version = \"#{version}\"."
89
- end
96
+ ". Your request did not specify an API version.".freeze
97
+ else
98
+ ". Your request speficied API version = \"#{version}\"."
99
+ end
90
100
  pretty_versions = attempted_versions.collect(&:inspect).join(', ')
91
101
  body += " Available versions = #{pretty_versions}."
92
102
  end
@@ -0,0 +1,51 @@
1
+ # Originally from:
2
+ # https://github.com/rkh/mustermann/blob/500a603fffe0594ab842d72addcc449eedd6d5be/mustermann/lib/mustermann/router/rack.rb
3
+ # Copied here after its removal from Mustermann proper
4
+
5
+ require 'praxis/router/simple'
6
+
7
+ module Mustermann
8
+ module Router
9
+ # Simple pattern based router that allows matching paths to a given Rack application.
10
+ #
11
+ # @example config.ru
12
+ # router = Mustermann::Rack.new do
13
+ # on '/' do |env|
14
+ # [200, {'Content-Type' => 'text/plain'}, ['Hello World!']]
15
+ # end
16
+ #
17
+ # on '/:name' do |env|
18
+ # name = env['mustermann.params']['name']
19
+ # [200, {'Content-Type' => 'text/plain'}, ["Hello #{name}!"]]
20
+ # end
21
+ #
22
+ # on '/something/*', call: SomeApp
23
+ # end
24
+ #
25
+ # # in a config.ru
26
+ # run router
27
+ class Rack < Simple
28
+ def initialize(env_prefix: "mustermann", params_key: "#{env_prefix}.params", pattern_key: "#{env_prefix}.pattern", **options, &block)
29
+ @params_key, @pattern_key = params_key, pattern_key
30
+ options[:default] = [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found"]] unless options.include? :default
31
+ super(**options, &block)
32
+ end
33
+
34
+ def invoke(callback, env, params, pattern)
35
+ params_was, pattern_was = env[@params_key], env[@pattern_key]
36
+ env[@params_key], env[@pattern_key] = params, pattern
37
+ response = callback.call(env)
38
+ response[1].each { |k,v| throw :pass if k.downcase == 'x-cascade' and v == 'pass' }
39
+ response
40
+ ensure
41
+ env[@params_key], env[@pattern_key] = params_was, pattern_was
42
+ end
43
+
44
+ def string_for(env)
45
+ env['PATH_INFO']
46
+ end
47
+
48
+ private :invoke, :string_for
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,146 @@
1
+ # Originally from:
2
+ # https://github.com/rkh/mustermann/blob/500a603fffe0594ab842d72addcc449eedd6d5be/mustermann/lib/mustermann/router/simple.rb
3
+ # Copied here after its removal from Mustermann proper
4
+
5
+ require 'mustermann'
6
+
7
+ module Mustermann
8
+ module Router
9
+ # Simple pattern based router that allows matching a string to a given callback.
10
+ #
11
+ # @example
12
+ # require 'mustermann/router/simple'
13
+ #
14
+ # router = Mustermann::Router::Simple.new do
15
+ # on ':name/:sub' do |string, params|
16
+ # params['sub']
17
+ # end
18
+ #
19
+ # on 'foo' do
20
+ # "bar"
21
+ # end
22
+ # end
23
+ #
24
+ # router.call("foo") # => "bar"
25
+ # router.call("a/b") # => "b"
26
+ # router.call("bar") # => nil
27
+ class Simple
28
+ # Default value for when no pattern matches
29
+ attr_accessor :default
30
+
31
+ # @example with a default value
32
+ # require 'mustermann/router/simple'
33
+ #
34
+ # router = Mustermann::Router::Simple.new(default: 42)
35
+ # router.on(':name', capture: :digit) { |string| string.to_i }
36
+ # router.call("23") # => 23
37
+ # router.call("example") # => 42
38
+ #
39
+ # @example block with implicit receiver
40
+ # require 'mustermann/router/simple'
41
+ #
42
+ # router = Mustermann::Router::Simple.new do
43
+ # on('/foo') { 'foo' }
44
+ # on('/bar') { 'bar' }
45
+ # end
46
+ #
47
+ # @example block with explicit receiver
48
+ # require 'mustermann/router/simple'
49
+ #
50
+ # router = Mustermann::Router::Simple.new(type: :rails) do |r|
51
+ # r.on('/foo') { 'foo' }
52
+ # r.on('/bar') { 'bar' }
53
+ # end
54
+ #
55
+ # @param default value to be returned if nothing matches
56
+ # @param options [Hash] pattern options
57
+ # @return [Mustermann::Router::Simple] new router instance
58
+ def initialize(default: nil, **options, &block)
59
+ @options = options
60
+ @map = []
61
+ @default = default
62
+
63
+ block.arity == 0 ? instance_eval(&block) : yield(self) if block
64
+ end
65
+
66
+ # @example
67
+ # require 'mustermann/router/simple'
68
+ #
69
+ # router = Mustermann::Router::Simple.new
70
+ # router.on(':a/:b') { 42 }
71
+ # router['foo/bar'] # => <#Proc:...>
72
+ # router['foo_bar'] # => nil
73
+ #
74
+ # @return [#call, nil] callback for given string, if a pattern matches
75
+ def [](string)
76
+ string = string_for(string) unless string.is_a? String
77
+ @map.detect { |p,v| p === string }[1]
78
+ end
79
+
80
+ # @example
81
+ # require 'mustermann/router/simple'
82
+ #
83
+ # router = Mustermann::Router::Simple.new
84
+ # router['/:name'] = proc { |string, params| params['name'] }
85
+ # router.call('/foo') # => "foo"
86
+ #
87
+ # @param pattern [String, Mustermann::Pattern] matcher
88
+ # @param callback [#call] callback to call on match
89
+ # @see #on
90
+ def []=(pattern, callback)
91
+ on(pattern, call: callback)
92
+ end
93
+
94
+ # @example with block
95
+ # require 'mustermann/router/simple'
96
+ #
97
+ # router = Mustermann::Router::Simple.new
98
+ #
99
+ # router.on(':a/:b') { 42 }
100
+ # router.call('foo/bar') # => 42
101
+ # router.call('foo_bar') # => nil
102
+ #
103
+ # @example with callback option
104
+ # require 'mustermann/router/simple'
105
+ #
106
+ # callback = proc { 42 }
107
+ # router = Mustermann::Router::Simple.new
108
+ #
109
+ # router.on(':a/:b', call: callback)
110
+ # router.call('foo/bar') # => 42
111
+ # router.call('foo_bar') # => nil
112
+ #
113
+ # @param patterns [Array<String, Pattern>]
114
+ # @param call [#call] callback object, need to hand in block if missing
115
+ # @param options [Hash] pattern options
116
+ def on(*patterns, call: Proc.new, **options)
117
+ patterns.each do |pattern|
118
+ pattern = Mustermann.new(pattern.to_str, **options, **@options) if pattern.respond_to? :to_str
119
+ @map << [pattern, call]
120
+ end
121
+ end
122
+
123
+ # Finds the matching callback and calls `call` on it with the given input and the params.
124
+ # @return the callback's return value
125
+ def call(input)
126
+ @map.each do |pattern, callback|
127
+ catch(:pass) do
128
+ next unless params = pattern.params(string_for(input))
129
+ return invoke(callback, input, params, pattern)
130
+ end
131
+ end
132
+ @default
133
+ end
134
+
135
+ def invoke(callback, input, params, pattern)
136
+ callback.call(input, params)
137
+ end
138
+
139
+ def string_for(input)
140
+ input.to_str
141
+ end
142
+
143
+ private :invoke, :string_for
144
+ end
145
+ end
146
+ end