grape 1.8.0 → 4.0.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 (317) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +517 -1
  3. data/CONTRIBUTING.md +19 -11
  4. data/README.md +841 -545
  5. data/UPGRADING.md +1553 -7
  6. data/grape.gemspec +11 -14
  7. data/lib/grape/api/instance.rb +77 -160
  8. data/lib/grape/api.rb +75 -107
  9. data/lib/grape/content_types.rb +67 -9
  10. data/lib/grape/cookies.rb +28 -25
  11. data/lib/grape/declared_params_handler.rb +116 -0
  12. data/lib/grape/dry_types.rb +48 -6
  13. data/lib/grape/dsl/callbacks.rb +8 -58
  14. data/lib/grape/dsl/declared.rb +35 -0
  15. data/lib/grape/dsl/desc.rb +25 -63
  16. data/lib/grape/dsl/entity.rb +106 -0
  17. data/lib/grape/dsl/headers.rb +2 -2
  18. data/lib/grape/dsl/helpers.rb +83 -64
  19. data/lib/grape/dsl/inside_route.rb +69 -296
  20. data/lib/grape/dsl/logger.rb +4 -9
  21. data/lib/grape/dsl/middleware.rb +22 -40
  22. data/lib/grape/dsl/parameters.rb +88 -94
  23. data/lib/grape/dsl/request_response.rb +143 -147
  24. data/lib/grape/dsl/rescue_options.rb +25 -0
  25. data/lib/grape/dsl/routing.rb +333 -191
  26. data/lib/grape/dsl/settings.rb +29 -135
  27. data/lib/grape/dsl/validations.rb +39 -32
  28. data/lib/grape/dsl/version_options.rb +23 -0
  29. data/lib/grape/endpoint/options.rb +25 -0
  30. data/lib/grape/endpoint.rb +319 -269
  31. data/lib/grape/{util/env.rb → env.rb} +8 -8
  32. data/lib/grape/error_formatter/base.rb +57 -21
  33. data/lib/grape/error_formatter/json.rb +13 -15
  34. data/lib/grape/error_formatter/serializable_hash.rb +7 -0
  35. data/lib/grape/error_formatter/txt.rb +12 -18
  36. data/lib/grape/error_formatter/xml.rb +3 -13
  37. data/lib/grape/error_formatter.rb +9 -25
  38. data/lib/grape/exceptions/base.rb +22 -58
  39. data/lib/grape/exceptions/error_response.rb +48 -0
  40. data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
  41. data/lib/grape/exceptions/internal_server_error.rb +16 -0
  42. data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
  43. data/lib/grape/exceptions/invalid_formatter.rb +1 -1
  44. data/lib/grape/exceptions/invalid_message_body.rb +1 -1
  45. data/lib/grape/exceptions/invalid_version_header.rb +1 -1
  46. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
  47. data/lib/grape/exceptions/method_not_allowed.rb +1 -1
  48. data/lib/grape/exceptions/missing_group_type.rb +0 -2
  49. data/lib/grape/exceptions/missing_mime_type.rb +1 -1
  50. data/lib/grape/exceptions/request_error.rb +11 -0
  51. data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
  52. data/lib/grape/exceptions/unknown_error_formatter.rb +11 -0
  53. data/lib/grape/exceptions/unknown_parameter.rb +1 -1
  54. data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
  55. data/lib/grape/exceptions/unknown_validator.rb +1 -1
  56. data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
  57. data/lib/grape/exceptions/validation.rb +28 -11
  58. data/lib/grape/exceptions/validation_array_errors.rb +5 -0
  59. data/lib/grape/exceptions/validation_errors.rb +22 -26
  60. data/lib/grape/formatter/base.rb +16 -0
  61. data/lib/grape/formatter/json.rb +5 -6
  62. data/lib/grape/formatter/serializable_hash.rb +7 -10
  63. data/lib/grape/formatter/txt.rb +3 -5
  64. data/lib/grape/formatter/xml.rb +4 -6
  65. data/lib/grape/formatter.rb +7 -25
  66. data/lib/grape/json.rb +46 -0
  67. data/lib/grape/locale/en.yml +44 -42
  68. data/lib/grape/middleware/auth/base.rb +11 -33
  69. data/lib/grape/middleware/auth/dsl.rb +12 -34
  70. data/lib/grape/middleware/auth/strategies.rb +1 -2
  71. data/lib/grape/middleware/base.rb +56 -33
  72. data/lib/grape/middleware/error.rb +290 -91
  73. data/lib/grape/middleware/formatter.rb +164 -106
  74. data/lib/grape/middleware/precomputed_content_types.rb +51 -0
  75. data/lib/grape/middleware/stack.rb +38 -40
  76. data/lib/grape/middleware/versioner/accept_version_header.rb +6 -33
  77. data/lib/grape/middleware/versioner/base.rb +66 -0
  78. data/lib/grape/middleware/versioner/header.rb +44 -129
  79. data/lib/grape/middleware/versioner/param.rb +4 -25
  80. data/lib/grape/middleware/versioner/path.rb +48 -25
  81. data/lib/grape/middleware/versioner.rb +7 -14
  82. data/lib/grape/mountable.rb +22 -0
  83. data/lib/grape/namespace.rb +21 -14
  84. data/lib/grape/params_builder/base.rb +20 -0
  85. data/lib/grape/params_builder/hash.rb +11 -0
  86. data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
  87. data/lib/grape/params_builder/hashie_mash.rb +11 -0
  88. data/lib/grape/params_builder.rb +15 -0
  89. data/lib/grape/parser/base.rb +16 -0
  90. data/lib/grape/parser/json.rb +6 -8
  91. data/lib/grape/parser/xml.rb +6 -8
  92. data/lib/grape/parser.rb +5 -23
  93. data/lib/grape/path.rb +8 -94
  94. data/lib/grape/precompiled_json.rb +50 -0
  95. data/lib/grape/railtie.rb +9 -0
  96. data/lib/grape/request.rb +200 -26
  97. data/lib/grape/router/base_route.rb +85 -0
  98. data/lib/grape/router/greedy_route.rb +30 -0
  99. data/lib/grape/router/mustermann_pattern.rb +44 -0
  100. data/lib/grape/router/pattern/path.rb +78 -0
  101. data/lib/grape/router/pattern.rb +77 -35
  102. data/lib/grape/router/route.rb +79 -60
  103. data/lib/grape/router.rb +128 -104
  104. data/lib/grape/serve_stream/file_body.rb +7 -0
  105. data/lib/grape/serve_stream/sendfile_response.rb +3 -5
  106. data/lib/grape/serve_stream/stream_response.rb +7 -0
  107. data/lib/grape/testing.rb +33 -0
  108. data/lib/grape/util/api_description.rb +67 -0
  109. data/lib/grape/util/cache.rb +22 -5
  110. data/lib/grape/util/deep_freeze.rb +34 -0
  111. data/lib/grape/util/endpoint_configuration.rb +1 -1
  112. data/lib/grape/util/freeze_on_new.rb +20 -0
  113. data/lib/grape/util/header.rb +13 -0
  114. data/lib/grape/util/inheritable_setting.rb +777 -39
  115. data/lib/grape/util/lazy/base.rb +16 -0
  116. data/lib/grape/util/lazy/block.rb +22 -0
  117. data/lib/grape/util/lazy/value.rb +31 -0
  118. data/lib/grape/util/lazy/value_array.rb +21 -0
  119. data/lib/grape/util/lazy/value_enumerable.rb +31 -0
  120. data/lib/grape/util/lazy/value_hash.rb +21 -0
  121. data/lib/grape/util/media_type.rb +74 -0
  122. data/lib/grape/util/path_normalizer.rb +37 -0
  123. data/lib/grape/util/registry.rb +37 -0
  124. data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
  125. data/lib/grape/util/stackable_values.rb +40 -16
  126. data/lib/grape/util/translation.rb +42 -0
  127. data/lib/grape/validations/attributes_iterator.rb +61 -28
  128. data/lib/grape/validations/coerce_options.rb +21 -0
  129. data/lib/grape/validations/contract_scope.rb +29 -0
  130. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  131. data/lib/grape/validations/oneof_collector.rb +35 -0
  132. data/lib/grape/validations/param_scope_tracker.rb +62 -0
  133. data/lib/grape/validations/params_documentation.rb +52 -0
  134. data/lib/grape/validations/params_scope.rb +223 -306
  135. data/lib/grape/validations/shared_options.rb +19 -0
  136. data/lib/grape/validations/single_attribute_iterator.rb +6 -4
  137. data/lib/grape/validations/types/array_coercer.rb +7 -12
  138. data/lib/grape/validations/types/custom_type_coercer.rb +47 -85
  139. data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
  140. data/lib/grape/validations/types/dry_type_coercer.rb +17 -28
  141. data/lib/grape/validations/types/json.rb +1 -5
  142. data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
  143. data/lib/grape/validations/types/primitive_coercer.rb +14 -35
  144. data/lib/grape/validations/types/set_coercer.rb +1 -4
  145. data/lib/grape/validations/types/variant_collection_coercer.rb +16 -3
  146. data/lib/grape/validations/types.rb +29 -54
  147. data/lib/grape/validations/validations_spec.rb +164 -0
  148. data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
  149. data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
  150. data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
  151. data/lib/grape/validations/validators/base.rb +118 -37
  152. data/lib/grape/validations/validators/coerce_validator.rb +26 -38
  153. data/lib/grape/validations/validators/contract_scope_validator.rb +46 -0
  154. data/lib/grape/validations/validators/default_validator.rb +13 -16
  155. data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
  156. data/lib/grape/validations/validators/except_values_validator.rb +15 -5
  157. data/lib/grape/validations/validators/length_validator.rb +50 -0
  158. data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
  159. data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
  160. data/lib/grape/validations/validators/oneof_validator.rb +51 -0
  161. data/lib/grape/validations/validators/presence_validator.rb +4 -2
  162. data/lib/grape/validations/validators/regexp_validator.rb +11 -3
  163. data/lib/grape/validations/validators/same_as_validator.rb +7 -15
  164. data/lib/grape/validations/validators/values_validator.rb +36 -65
  165. data/lib/grape/validations.rb +8 -21
  166. data/lib/grape/version.rb +1 -2
  167. data/lib/grape/xml.rb +17 -0
  168. data/lib/grape.rb +96 -288
  169. metadata +83 -294
  170. data/lib/grape/api/helpers.rb +0 -9
  171. data/lib/grape/dsl/api.rb +0 -19
  172. data/lib/grape/dsl/configuration.rb +0 -15
  173. data/lib/grape/eager_load.rb +0 -20
  174. data/lib/grape/exceptions/empty_message_body.rb +0 -11
  175. data/lib/grape/exceptions/missing_option.rb +0 -11
  176. data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
  177. data/lib/grape/exceptions/unknown_options.rb +0 -11
  178. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -27
  179. data/lib/grape/extensions/hash.rb +0 -22
  180. data/lib/grape/extensions/hashie/mash.rb +0 -26
  181. data/lib/grape/http/headers.rb +0 -61
  182. data/lib/grape/middleware/globals.rb +0 -16
  183. data/lib/grape/middleware/helpers.rb +0 -12
  184. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
  185. data/lib/grape/router/attribute_translator.rb +0 -63
  186. data/lib/grape/types/invalid_value.rb +0 -8
  187. data/lib/grape/util/base_inheritable.rb +0 -43
  188. data/lib/grape/util/inheritable_values.rb +0 -31
  189. data/lib/grape/util/json.rb +0 -12
  190. data/lib/grape/util/lazy_block.rb +0 -27
  191. data/lib/grape/util/lazy_object.rb +0 -43
  192. data/lib/grape/util/lazy_value.rb +0 -91
  193. data/lib/grape/util/registrable.rb +0 -15
  194. data/lib/grape/util/reverse_stackable_values.rb +0 -20
  195. data/lib/grape/util/strict_hash_configuration.rb +0 -108
  196. data/lib/grape/util/xml.rb +0 -10
  197. data/lib/grape/validations/attributes_doc.rb +0 -58
  198. data/lib/grape/validations/types/build_coercer.rb +0 -94
  199. data/lib/grape/validations/validator_factory.rb +0 -15
  200. data/spec/grape/api/custom_validations_spec.rb +0 -213
  201. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  202. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  203. data/spec/grape/api/documentation_spec.rb +0 -59
  204. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  205. data/spec/grape/api/instance_spec.rb +0 -103
  206. data/spec/grape/api/invalid_format_spec.rb +0 -45
  207. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  208. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  209. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  210. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  211. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  212. data/spec/grape/api/recognize_path_spec.rb +0 -21
  213. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  214. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  215. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  216. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  217. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  218. data/spec/grape/api_remount_spec.rb +0 -509
  219. data/spec/grape/api_spec.rb +0 -4356
  220. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  221. data/spec/grape/dsl/desc_spec.rb +0 -98
  222. data/spec/grape/dsl/headers_spec.rb +0 -62
  223. data/spec/grape/dsl/helpers_spec.rb +0 -100
  224. data/spec/grape/dsl/inside_route_spec.rb +0 -531
  225. data/spec/grape/dsl/logger_spec.rb +0 -24
  226. data/spec/grape/dsl/middleware_spec.rb +0 -60
  227. data/spec/grape/dsl/parameters_spec.rb +0 -180
  228. data/spec/grape/dsl/request_response_spec.rb +0 -225
  229. data/spec/grape/dsl/routing_spec.rb +0 -275
  230. data/spec/grape/dsl/settings_spec.rb +0 -261
  231. data/spec/grape/dsl/validations_spec.rb +0 -55
  232. data/spec/grape/endpoint/declared_spec.rb +0 -846
  233. data/spec/grape/endpoint_spec.rb +0 -1085
  234. data/spec/grape/entity_spec.rb +0 -336
  235. data/spec/grape/exceptions/base_spec.rb +0 -81
  236. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
  237. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  238. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  239. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  240. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  241. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
  242. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  243. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  244. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  245. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  246. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
  247. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  248. data/spec/grape/exceptions/validation_spec.rb +0 -19
  249. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  250. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  251. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  252. data/spec/grape/grape_spec.rb +0 -9
  253. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  254. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  255. data/spec/grape/integration/rack_spec.rb +0 -51
  256. data/spec/grape/loading_spec.rb +0 -44
  257. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  258. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  259. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  260. data/spec/grape/middleware/base_spec.rb +0 -221
  261. data/spec/grape/middleware/error_spec.rb +0 -85
  262. data/spec/grape/middleware/exception_spec.rb +0 -294
  263. data/spec/grape/middleware/formatter_spec.rb +0 -461
  264. data/spec/grape/middleware/globals_spec.rb +0 -30
  265. data/spec/grape/middleware/stack_spec.rb +0 -155
  266. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  267. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  268. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  269. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  270. data/spec/grape/middleware/versioner_spec.rb +0 -21
  271. data/spec/grape/named_api_spec.rb +0 -19
  272. data/spec/grape/parser_spec.rb +0 -86
  273. data/spec/grape/path_spec.rb +0 -252
  274. data/spec/grape/presenters/presenter_spec.rb +0 -71
  275. data/spec/grape/request_spec.rb +0 -126
  276. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  277. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  278. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  279. data/spec/grape/util/stackable_values_spec.rb +0 -128
  280. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  281. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  282. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  283. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
  284. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  285. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
  286. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  287. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  288. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  289. data/spec/grape/validations/types_spec.rb +0 -111
  290. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  291. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  292. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  293. data/spec/grape/validations/validators/base_spec.rb +0 -38
  294. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  295. data/spec/grape/validations/validators/default_spec.rb +0 -463
  296. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  297. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  298. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  299. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  300. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  301. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  302. data/spec/grape/validations/validators/values_spec.rb +0 -733
  303. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  304. data/spec/grape/validations_spec.rb +0 -2030
  305. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  306. data/spec/integration/multi_json/json_spec.rb +0 -7
  307. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  308. data/spec/shared/deprecated_class_examples.rb +0 -16
  309. data/spec/shared/versioning_examples.rb +0 -215
  310. data/spec/spec_helper.rb +0 -52
  311. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  312. data/spec/support/chunks.rb +0 -14
  313. data/spec/support/content_type_helpers.rb +0 -15
  314. data/spec/support/endpoint_faker.rb +0 -25
  315. data/spec/support/file_streamer.rb +0 -13
  316. data/spec/support/integer_helpers.rb +0 -13
  317. data/spec/support/versioned_helpers.rb +0 -55
@@ -7,172 +7,66 @@ module Grape
7
7
  # matter where they're defined, and inheritable settings which apply only
8
8
  # in the current scope and scopes nested under it.
9
9
  module Settings
10
- extend ActiveSupport::Concern
11
-
12
- attr_writer :inheritable_setting, :top_level_setting
10
+ attr_writer :inheritable_setting
13
11
 
14
12
  # Fetch our top-level settings, which apply to all endpoints in the API.
15
13
  def top_level_setting
16
- @top_level_setting ||= build_top_level_setting
14
+ return @top_level_setting if @top_level_setting
15
+
16
+ @top_level_setting = Grape::Util::InheritableSetting.new
17
+ # Doesn't try to inherit settings from +Grape::API::Instance+ which also responds to
18
+ # +inheritable_setting+, however, it doesn't contain any user-defined settings.
19
+ # Otherwise, it would lead to an extra instance of +Grape::Util::InheritableSetting+
20
+ # in the chain for every endpoint.
21
+ @top_level_setting.inherit_from superclass.inheritable_setting if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
22
+ @top_level_setting
17
23
  end
18
24
 
19
25
  # Fetch our current inheritable settings, which are inherited by
20
26
  # nested scopes but not shared across siblings.
21
27
  def inheritable_setting
22
- @inheritable_setting ||= Grape::Util::InheritableSetting.new.tap { |new_settings| new_settings.inherit_from top_level_setting }
23
- end
28
+ return @inheritable_setting if @inheritable_setting
24
29
 
25
- # @param type [Symbol]
26
- # @param key [Symbol]
27
- def unset(type, key)
28
- setting = inheritable_setting.send(type)
29
- setting.delete key
30
+ @inheritable_setting = Grape::Util::InheritableSetting.new
31
+ @inheritable_setting.inherit_from top_level_setting
32
+ @inheritable_setting
30
33
  end
31
34
 
32
- # @param type [Symbol]
33
- # @param key [Symbol]
34
- # @param value [Object] will be stored if the value is currently empty
35
- # @return either the old value, if it wasn't nil, or the given value
36
- def get_or_set(type, key, value)
37
- setting = inheritable_setting.send(type)
38
- if value.nil?
39
- setting[key]
40
- else
41
- setting[key] = value
42
- end
43
- end
44
-
45
- # @param key [Symbol]
46
- # @param value [Object]
47
- # @return (see #get_or_set)
48
35
  def global_setting(key, value = nil)
49
- get_or_set :global, key, value
50
- end
51
-
52
- # @param key [Symbol]
53
- def unset_global_setting(key)
54
- unset :global, key
36
+ get_or_set(inheritable_setting.global, key, value)
55
37
  end
56
38
 
57
- # (see #global_setting)
58
39
  def route_setting(key, value = nil)
59
- get_or_set :route, key, value
60
- end
61
-
62
- # (see #unset_global_setting)
63
- def unset_route_setting(key)
64
- unset :route, key
40
+ inheritable_setting.route_setting(key, value)
65
41
  end
66
42
 
67
- # (see #global_setting)
68
43
  def namespace_setting(key, value = nil)
69
- get_or_set :namespace, key, value
44
+ get_or_set(inheritable_setting.namespace, key, value)
70
45
  end
71
46
 
72
- # (see #unset_global_setting)
73
- def unset_namespace_setting(key)
74
- unset :namespace, key
75
- end
76
-
77
- # (see #global_setting)
78
- def namespace_inheritable(key, value = nil)
79
- get_or_set :namespace_inheritable, key, value
80
- end
81
-
82
- # (see #unset_global_setting)
83
- def unset_namespace_inheritable(key)
84
- unset :namespace_inheritable, key
85
- end
86
-
87
- # @param key [Symbol]
88
- def namespace_inheritable_to_nil(key)
89
- inheritable_setting.namespace_inheritable[key] = nil
90
- end
91
-
92
- # (see #global_setting)
93
- def namespace_stackable(key, value = nil)
94
- get_or_set :namespace_stackable, key, value
95
- end
96
-
97
- def namespace_reverse_stackable(key, value = nil)
98
- get_or_set :namespace_reverse_stackable, key, value
99
- end
100
-
101
- def namespace_stackable_with_hash(key)
102
- settings = get_or_set :namespace_stackable, key, nil
103
- return if settings.blank?
104
-
105
- settings.each_with_object({}) { |value, result| result.deep_merge!(value) }
106
- end
107
-
108
- def namespace_reverse_stackable_with_hash(key)
109
- settings = get_or_set :namespace_reverse_stackable, key, nil
110
- return if settings.blank?
111
-
112
- settings.each_with_object({}) do |setting, result|
113
- result.merge!(setting) { |_k, s1, _s2| s1 }
114
- end
115
- end
116
-
117
- # (see #unset_global_setting)
118
- def unset_namespace_stackable(key)
119
- unset :namespace_stackable, key
120
- end
121
-
122
- # (see #global_setting)
123
- def api_class_setting(key, value = nil)
124
- get_or_set :api_class, key, value
125
- end
126
-
127
- # (see #unset_global_setting)
128
- def unset_api_class_setting(key)
129
- unset :api_class, key
130
- end
131
-
132
- # Fork our inheritable settings to a new instance, copied from our
133
- # parent's, but separate so we won't modify it. Every call to this
134
- # method should have an answering call to #namespace_end.
135
- def namespace_start
136
- @inheritable_setting = Grape::Util::InheritableSetting.new.tap { |new_settings| new_settings.inherit_from inheritable_setting }
137
- end
138
-
139
- # Set the inheritable settings pointer back up by one level.
140
- def namespace_end
141
- route_end
142
- @inheritable_setting = inheritable_setting.parent
143
- end
144
-
145
- # Stop defining settings for the current route and clear them for the
146
- # next, within a namespace.
147
- def route_end
148
- inheritable_setting.route_end
149
- end
47
+ private
150
48
 
151
49
  # Execute the block within a context where our inheritable settings are forked
152
50
  # to a new copy (see #namespace_start).
153
- def within_namespace(&block)
154
- namespace_start
51
+ def within_namespace
52
+ new_inheritable_settings = Grape::Util::InheritableSetting.new
53
+ new_inheritable_settings.inherit_from inheritable_setting
54
+
55
+ @inheritable_setting = new_inheritable_settings
155
56
 
156
- result = yield if block
57
+ result = yield
157
58
 
158
- namespace_end
59
+ inheritable_setting.route_end
60
+ @inheritable_setting = inheritable_setting.parent
159
61
  reset_validations!
160
62
 
161
63
  result
162
64
  end
163
65
 
164
- private
66
+ def get_or_set(setting, key, value)
67
+ return setting[key] if value.nil?
165
68
 
166
- # Builds the current class :inheritable_setting. If available, it inherits from
167
- # the superclass's :inheritable_setting.
168
- def build_top_level_setting
169
- Grape::Util::InheritableSetting.new.tap do |setting|
170
- # Doesn't try to inherit settings from +Grape::API::Instance+ which also responds to
171
- # +inheritable_setting+, however, it doesn't contain any user-defined settings.
172
- # Otherwise, it would lead to an extra instance of +Grape::Util::InheritableSetting+
173
- # in the chain for every endpoint.
174
- setting.inherit_from superclass.inheritable_setting if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
175
- end
69
+ setting[key] = value
176
70
  end
177
71
  end
178
72
  end
@@ -3,41 +3,48 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Validations
6
- extend ActiveSupport::Concern
6
+ # Opens a root-level ParamsScope, defining parameter coercions and
7
+ # validations for the endpoint.
8
+ # @yield instance context of the new scope
9
+ def params(&)
10
+ Grape::Validations::ParamsScope.new(api: self, type: Hash, &)
11
+ end
12
+
13
+ # Declare the contract to be used for the endpoint's parameters.
14
+ # @param contract [Class<Dry::Validation::Contract> | Dry::Schema::Processor]
15
+ # The contract or schema to be used for validation. Optional.
16
+ # @yield a block yielding a new instance of Dry::Schema::Params
17
+ # subclass, allowing to define the schema inline. When the
18
+ # +contract+ parameter is a schema, it will be used as a parent. Optional.
19
+ def contract(contract = nil, &block)
20
+ raise ArgumentError, 'either contract or block must be provided' unless contract || block
21
+ raise ArgumentError, 'cannot inherit from contract, only schema' if block && contract.respond_to?(:schema)
7
22
 
8
- include Grape::DSL::Configuration
23
+ Grape::Validations::ContractScope.new(self, contract, &block)
24
+ end
9
25
 
10
- module ClassMethods
11
- # Clears all defined parameters and validations. The main purpose of it is to clean up
12
- # settings, so next endpoint won't interfere with previous one.
13
- #
14
- # params do
15
- # # params for the endpoint below this block
16
- # end
17
- # post '/current' do
18
- # # whatever
19
- # end
20
- #
21
- # # somewhere between them the reset_validations! method gets called
22
- #
23
- # params do
24
- # # params for the endpoint below this block
25
- # end
26
- # post '/next' do
27
- # # whatever
28
- # end
29
- def reset_validations!
30
- unset_namespace_stackable :declared_params
31
- unset_namespace_stackable :validations
32
- unset_namespace_stackable :params
33
- end
26
+ private
34
27
 
35
- # Opens a root-level ParamsScope, defining parameter coercions and
36
- # validations for the endpoint.
37
- # @yield instance context of the new scope
38
- def params(&block)
39
- Grape::Validations::ParamsScope.new(api: self, type: Hash, &block)
40
- end
28
+ # Clears all defined parameters and validations. The main purpose of it is to clean up
29
+ # settings, so next endpoint won't interfere with previous one.
30
+ #
31
+ # params do
32
+ # # params for the endpoint below this block
33
+ # end
34
+ # post '/current' do
35
+ # # whatever
36
+ # end
37
+ #
38
+ # # somewhere between them the reset_validations! method gets called
39
+ #
40
+ # params do
41
+ # # params for the endpoint below this block
42
+ # end
43
+ # post '/next' do
44
+ # # whatever
45
+ # end
46
+ def reset_validations!
47
+ inheritable_setting.reset_validations!
41
48
  end
42
49
  end
43
50
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grape
4
+ module DSL
5
+ # Immutable value object holding the resolved options from
6
+ # +Grape::DSL::Routing#version+. Stored on the inheritable settings as
7
+ # +Grape::Util::InheritableSetting#version_options+ and read by internal call
8
+ # sites (`Path`, `Endpoint`, `API::Instance#cascade?`,
9
+ # `Middleware::Versioner::Base`) via accessors.
10
+ #
11
+ # Defaults are duplicated on +#initialize+ here and on +#version+'s
12
+ # signature on purpose: keeping them on both sides means each entry point
13
+ # is self-documenting without needing to import a shared constant — the
14
+ # DSL signature shows what a user sees in the IDE, and the Data object
15
+ # has working defaults when constructed directly (spec fixtures, a
16
+ # middleware built by hand). The two must stay in lockstep.
17
+ VersionOptions = Data.define(:using, :cascade, :parameter, :strict, :vendor) do
18
+ def initialize(using: :path, cascade: true, parameter: 'apiver', strict: false, vendor: nil)
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grape
4
+ class Endpoint
5
+ # Immutable value object holding the keyword inputs passed to
6
+ # +Grape::Endpoint.new+. Internal to {Grape::Endpoint}, which builds it
7
+ # from the +**options+ Hash in #initialize so the public +options+ reader
8
+ # stays a plain Hash for downstream gems (e.g. grape-swagger).
9
+ Options = Data.define(:path, :http_methods, :api, :route_options, :app, :params, :requirements, :anchor) do
10
+ def initialize(path:, http_methods:, api:, route_options: {}, app: nil, params: {}, requirements: nil, anchor: true)
11
+ # +Array()+ hands back the very Array it was given, so defaulting an
12
+ # empty one by appending would append to the caller's Array — and raise
13
+ # FrozenError on a frozen one. Build a new Array instead of growing
14
+ # theirs: nothing about constructing an endpoint should be visible in
15
+ # the path the caller passed in.
16
+ paths = Array(path)
17
+ super(
18
+ path: paths.presence || ['/'],
19
+ http_methods: Array(http_methods),
20
+ api:, route_options:, app:, params:, requirements:, anchor:
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end