grape 1.8.0 → 3.3.5

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 (312) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +391 -1
  3. data/CONTRIBUTING.md +3 -11
  4. data/README.md +648 -552
  5. data/UPGRADING.md +803 -7
  6. data/grape.gemspec +11 -14
  7. data/lib/grape/api/instance.rb +68 -158
  8. data/lib/grape/api.rb +71 -107
  9. data/lib/grape/content_types.rb +23 -11
  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 +14 -58
  14. data/lib/grape/dsl/declared.rb +35 -0
  15. data/lib/grape/dsl/desc.rb +15 -63
  16. data/lib/grape/dsl/entity.rb +88 -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 +56 -295
  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 +50 -82
  23. data/lib/grape/dsl/request_response.rb +144 -146
  24. data/lib/grape/dsl/rescue_options.rb +24 -0
  25. data/lib/grape/dsl/routing.rb +261 -186
  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 +19 -0
  30. data/lib/grape/endpoint.rb +277 -250
  31. data/lib/grape/{util/env.rb → env.rb} +1 -8
  32. data/lib/grape/error_formatter/base.rb +56 -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 +5 -25
  38. data/lib/grape/exceptions/base.rb +22 -58
  39. data/lib/grape/exceptions/error_response.rb +45 -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_parameter.rb +1 -1
  53. data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
  54. data/lib/grape/exceptions/unknown_validator.rb +1 -1
  55. data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
  56. data/lib/grape/exceptions/validation.rb +25 -9
  57. data/lib/grape/exceptions/validation_array_errors.rb +5 -0
  58. data/lib/grape/exceptions/validation_errors.rb +22 -26
  59. data/lib/grape/formatter/base.rb +16 -0
  60. data/lib/grape/formatter/json.rb +4 -6
  61. data/lib/grape/formatter/serializable_hash.rb +6 -10
  62. data/lib/grape/formatter/txt.rb +3 -5
  63. data/lib/grape/formatter/xml.rb +4 -6
  64. data/lib/grape/formatter.rb +7 -25
  65. data/lib/grape/json.rb +46 -0
  66. data/lib/grape/locale/en.yml +43 -42
  67. data/lib/grape/middleware/auth/base.rb +11 -33
  68. data/lib/grape/middleware/auth/dsl.rb +37 -31
  69. data/lib/grape/middleware/auth/strategies.rb +1 -2
  70. data/lib/grape/middleware/base.rb +56 -33
  71. data/lib/grape/middleware/deprecated_options_hash_access.rb +19 -0
  72. data/lib/grape/middleware/error.rb +183 -91
  73. data/lib/grape/middleware/formatter.rb +94 -105
  74. data/lib/grape/middleware/precomputed_content_types.rb +46 -0
  75. data/lib/grape/middleware/stack.rb +27 -38
  76. data/lib/grape/middleware/versioner/accept_version_header.rb +6 -33
  77. data/lib/grape/middleware/versioner/base.rb +72 -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 +13 -32
  81. data/lib/grape/middleware/versioner.rb +7 -14
  82. data/lib/grape/mountable.rb +22 -0
  83. data/lib/grape/namespace.rb +18 -12
  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 +38 -63
  94. data/lib/grape/railtie.rb +9 -0
  95. data/lib/grape/request.rb +168 -26
  96. data/lib/grape/router/base_route.rb +48 -0
  97. data/lib/grape/router/greedy_route.rb +26 -0
  98. data/lib/grape/router/mustermann_pattern.rb +44 -0
  99. data/lib/grape/router/pattern.rb +30 -34
  100. data/lib/grape/router/route.rb +28 -61
  101. data/lib/grape/router.rb +71 -86
  102. data/lib/grape/serve_stream/file_body.rb +1 -0
  103. data/lib/grape/serve_stream/sendfile_response.rb +3 -5
  104. data/lib/grape/serve_stream/stream_response.rb +1 -0
  105. data/lib/grape/testing.rb +33 -0
  106. data/lib/grape/util/api_description.rb +58 -0
  107. data/lib/grape/util/base_inheritable.rb +14 -14
  108. data/lib/grape/util/cache.rb +1 -3
  109. data/lib/grape/util/deep_freeze.rb +35 -0
  110. data/lib/grape/util/endpoint_configuration.rb +1 -1
  111. data/lib/grape/util/header.rb +13 -0
  112. data/lib/grape/util/inheritable_setting.rb +51 -27
  113. data/lib/grape/util/inheritable_values.rb +7 -5
  114. data/lib/grape/util/lazy/base.rb +16 -0
  115. data/lib/grape/util/lazy/block.rb +22 -0
  116. data/lib/grape/util/lazy/value.rb +31 -0
  117. data/lib/grape/util/lazy/value_array.rb +21 -0
  118. data/lib/grape/util/lazy/value_enumerable.rb +31 -0
  119. data/lib/grape/util/lazy/value_hash.rb +21 -0
  120. data/lib/grape/util/media_type.rb +67 -0
  121. data/lib/grape/util/path_normalizer.rb +34 -0
  122. data/lib/grape/util/registry.rb +27 -0
  123. data/lib/grape/util/reverse_stackable_values.rb +1 -6
  124. data/lib/grape/util/stackable_values.rb +12 -14
  125. data/lib/grape/util/translation.rb +42 -0
  126. data/lib/grape/validations/attributes_iterator.rb +43 -27
  127. data/lib/grape/validations/coerce_options.rb +21 -0
  128. data/lib/grape/validations/contract_scope.rb +28 -0
  129. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  130. data/lib/grape/validations/oneof_collector.rb +39 -0
  131. data/lib/grape/validations/param_scope_tracker.rb +62 -0
  132. data/lib/grape/validations/params_documentation.rb +52 -0
  133. data/lib/grape/validations/params_scope.rb +180 -303
  134. data/lib/grape/validations/shared_options.rb +19 -0
  135. data/lib/grape/validations/single_attribute_iterator.rb +2 -2
  136. data/lib/grape/validations/types/array_coercer.rb +4 -7
  137. data/lib/grape/validations/types/custom_type_coercer.rb +41 -85
  138. data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
  139. data/lib/grape/validations/types/dry_type_coercer.rb +15 -28
  140. data/lib/grape/validations/types/json.rb +0 -2
  141. data/lib/grape/validations/types/primitive_coercer.rb +11 -35
  142. data/lib/grape/validations/types/set_coercer.rb +1 -4
  143. data/lib/grape/validations/types/variant_collection_coercer.rb +11 -0
  144. data/lib/grape/validations/types.rb +29 -54
  145. data/lib/grape/validations/validations_spec.rb +164 -0
  146. data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
  147. data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
  148. data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
  149. data/lib/grape/validations/validators/base.rb +120 -36
  150. data/lib/grape/validations/validators/coerce_validator.rb +18 -36
  151. data/lib/grape/validations/validators/contract_scope_validator.rb +45 -0
  152. data/lib/grape/validations/validators/default_validator.rb +13 -16
  153. data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
  154. data/lib/grape/validations/validators/except_values_validator.rb +15 -5
  155. data/lib/grape/validations/validators/length_validator.rb +48 -0
  156. data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
  157. data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
  158. data/lib/grape/validations/validators/oneof_validator.rb +49 -0
  159. data/lib/grape/validations/validators/presence_validator.rb +4 -2
  160. data/lib/grape/validations/validators/regexp_validator.rb +11 -3
  161. data/lib/grape/validations/validators/same_as_validator.rb +6 -15
  162. data/lib/grape/validations/validators/values_validator.rb +36 -65
  163. data/lib/grape/validations.rb +8 -21
  164. data/lib/grape/version.rb +1 -2
  165. data/lib/grape/xml.rb +17 -0
  166. data/lib/grape.rb +75 -288
  167. metadata +79 -291
  168. data/lib/grape/api/helpers.rb +0 -9
  169. data/lib/grape/dsl/api.rb +0 -19
  170. data/lib/grape/dsl/configuration.rb +0 -15
  171. data/lib/grape/eager_load.rb +0 -20
  172. data/lib/grape/exceptions/empty_message_body.rb +0 -11
  173. data/lib/grape/exceptions/missing_option.rb +0 -11
  174. data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
  175. data/lib/grape/exceptions/unknown_options.rb +0 -11
  176. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -27
  177. data/lib/grape/extensions/hash.rb +0 -22
  178. data/lib/grape/extensions/hashie/mash.rb +0 -26
  179. data/lib/grape/http/headers.rb +0 -61
  180. data/lib/grape/middleware/globals.rb +0 -16
  181. data/lib/grape/middleware/helpers.rb +0 -12
  182. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
  183. data/lib/grape/router/attribute_translator.rb +0 -63
  184. data/lib/grape/types/invalid_value.rb +0 -8
  185. data/lib/grape/util/json.rb +0 -12
  186. data/lib/grape/util/lazy_block.rb +0 -27
  187. data/lib/grape/util/lazy_object.rb +0 -43
  188. data/lib/grape/util/lazy_value.rb +0 -91
  189. data/lib/grape/util/registrable.rb +0 -15
  190. data/lib/grape/util/strict_hash_configuration.rb +0 -108
  191. data/lib/grape/util/xml.rb +0 -10
  192. data/lib/grape/validations/attributes_doc.rb +0 -58
  193. data/lib/grape/validations/types/build_coercer.rb +0 -94
  194. data/lib/grape/validations/validator_factory.rb +0 -15
  195. data/spec/grape/api/custom_validations_spec.rb +0 -213
  196. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  197. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  198. data/spec/grape/api/documentation_spec.rb +0 -59
  199. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  200. data/spec/grape/api/instance_spec.rb +0 -103
  201. data/spec/grape/api/invalid_format_spec.rb +0 -45
  202. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  203. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  204. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  205. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  206. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  207. data/spec/grape/api/recognize_path_spec.rb +0 -21
  208. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  209. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  210. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  211. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  212. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  213. data/spec/grape/api_remount_spec.rb +0 -509
  214. data/spec/grape/api_spec.rb +0 -4356
  215. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  216. data/spec/grape/dsl/desc_spec.rb +0 -98
  217. data/spec/grape/dsl/headers_spec.rb +0 -62
  218. data/spec/grape/dsl/helpers_spec.rb +0 -100
  219. data/spec/grape/dsl/inside_route_spec.rb +0 -531
  220. data/spec/grape/dsl/logger_spec.rb +0 -24
  221. data/spec/grape/dsl/middleware_spec.rb +0 -60
  222. data/spec/grape/dsl/parameters_spec.rb +0 -180
  223. data/spec/grape/dsl/request_response_spec.rb +0 -225
  224. data/spec/grape/dsl/routing_spec.rb +0 -275
  225. data/spec/grape/dsl/settings_spec.rb +0 -261
  226. data/spec/grape/dsl/validations_spec.rb +0 -55
  227. data/spec/grape/endpoint/declared_spec.rb +0 -846
  228. data/spec/grape/endpoint_spec.rb +0 -1085
  229. data/spec/grape/entity_spec.rb +0 -336
  230. data/spec/grape/exceptions/base_spec.rb +0 -81
  231. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
  232. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  233. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  234. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  235. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  236. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
  237. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  238. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  239. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  240. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  241. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
  242. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  243. data/spec/grape/exceptions/validation_spec.rb +0 -19
  244. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  245. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  246. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  247. data/spec/grape/grape_spec.rb +0 -9
  248. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  249. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  250. data/spec/grape/integration/rack_spec.rb +0 -51
  251. data/spec/grape/loading_spec.rb +0 -44
  252. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  253. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  254. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  255. data/spec/grape/middleware/base_spec.rb +0 -221
  256. data/spec/grape/middleware/error_spec.rb +0 -85
  257. data/spec/grape/middleware/exception_spec.rb +0 -294
  258. data/spec/grape/middleware/formatter_spec.rb +0 -461
  259. data/spec/grape/middleware/globals_spec.rb +0 -30
  260. data/spec/grape/middleware/stack_spec.rb +0 -155
  261. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  262. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  263. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  264. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  265. data/spec/grape/middleware/versioner_spec.rb +0 -21
  266. data/spec/grape/named_api_spec.rb +0 -19
  267. data/spec/grape/parser_spec.rb +0 -86
  268. data/spec/grape/path_spec.rb +0 -252
  269. data/spec/grape/presenters/presenter_spec.rb +0 -71
  270. data/spec/grape/request_spec.rb +0 -126
  271. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  272. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  273. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  274. data/spec/grape/util/stackable_values_spec.rb +0 -128
  275. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  276. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  277. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  278. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
  279. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  280. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
  281. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  282. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  283. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  284. data/spec/grape/validations/types_spec.rb +0 -111
  285. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  286. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  287. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  288. data/spec/grape/validations/validators/base_spec.rb +0 -38
  289. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  290. data/spec/grape/validations/validators/default_spec.rb +0 -463
  291. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  292. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  293. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  294. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  295. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  296. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  297. data/spec/grape/validations/validators/values_spec.rb +0 -733
  298. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  299. data/spec/grape/validations_spec.rb +0 -2030
  300. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  301. data/spec/integration/multi_json/json_spec.rb +0 -7
  302. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  303. data/spec/shared/deprecated_class_examples.rb +0 -16
  304. data/spec/shared/versioning_examples.rb +0 -215
  305. data/spec/spec_helper.rb +0 -52
  306. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  307. data/spec/support/chunks.rb +0 -14
  308. data/spec/support/content_type_helpers.rb +0 -15
  309. data/spec/support/endpoint_faker.rb +0 -25
  310. data/spec/support/file_streamer.rb +0 -13
  311. data/spec/support/integer_helpers.rb +0 -13
  312. 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
+ get_or_set(inheritable_setting.route, 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.namespace_stackable.delete(:declared_params, :params, :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
+ # +namespace_inheritable[: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 (middleware
16
+ # `DEFAULT_OPTIONS`, spec fixtures, etc.). 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,19 @@
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
+ # +:method+ is renamed to +:http_methods+ on the value object to avoid
10
+ # shadowing +Object#method+ via the generated Data accessor.
11
+ Options = Data.define(:path, :http_methods, :for, :route_options, :app, :format, :forward_match) do
12
+ def initialize(path:, method:, route_options: {}, app: nil, format: nil, forward_match: nil, **rest)
13
+ path = Array(path)
14
+ path << '/' if path.empty?
15
+ super(path:, http_methods: Array(method), route_options:, app:, format:, forward_match:, **rest)
16
+ end
17
+ end
18
+ end
19
+ end