grape 1.6.2 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -1
  3. data/CONTRIBUTING.md +30 -0
  4. data/README.md +146 -23
  5. data/UPGRADING.md +15 -0
  6. data/grape.gemspec +2 -2
  7. data/lib/grape/api/instance.rb +1 -1
  8. data/lib/grape/dry_types.rb +12 -0
  9. data/lib/grape/dsl/api.rb +0 -2
  10. data/lib/grape/dsl/callbacks.rb +0 -2
  11. data/lib/grape/dsl/configuration.rb +0 -2
  12. data/lib/grape/dsl/desc.rb +2 -16
  13. data/lib/grape/dsl/helpers.rb +0 -2
  14. data/lib/grape/dsl/inside_route.rb +34 -30
  15. data/lib/grape/dsl/middleware.rb +0 -2
  16. data/lib/grape/dsl/parameters.rb +10 -7
  17. data/lib/grape/dsl/request_response.rb +1 -3
  18. data/lib/grape/dsl/routing.rb +4 -2
  19. data/lib/grape/dsl/settings.rb +0 -2
  20. data/lib/grape/dsl/validations.rb +0 -15
  21. data/lib/grape/endpoint.rb +2 -2
  22. data/lib/grape/error_formatter/json.rb +7 -1
  23. data/lib/grape/exceptions/base.rb +3 -2
  24. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  25. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  26. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  27. data/lib/grape/exceptions/validation.rb +0 -4
  28. data/lib/grape/locale/en.yml +9 -8
  29. data/lib/grape/middleware/auth/dsl.rb +0 -1
  30. data/lib/grape/middleware/error.rb +2 -2
  31. data/lib/grape/middleware/stack.rb +1 -1
  32. data/lib/grape/request.rb +3 -1
  33. data/lib/grape/router/attribute_translator.rb +1 -1
  34. data/lib/grape/types/invalid_value.rb +8 -0
  35. data/lib/grape/util/cache.rb +1 -1
  36. data/lib/grape/util/json.rb +2 -0
  37. data/lib/grape/validations/attributes_doc.rb +58 -0
  38. data/lib/grape/validations/params_scope.rb +67 -41
  39. data/lib/grape/validations/types/array_coercer.rb +0 -2
  40. data/lib/grape/validations/types/dry_type_coercer.rb +3 -7
  41. data/lib/grape/validations/types/invalid_value.rb +0 -7
  42. data/lib/grape/validations/types/primitive_coercer.rb +14 -6
  43. data/lib/grape/validations/types/set_coercer.rb +0 -2
  44. data/lib/grape/validations/types.rb +98 -30
  45. data/lib/grape/validations/validators/{all_or_none.rb → all_or_none_of_validator.rb} +0 -2
  46. data/lib/grape/validations/validators/{at_least_one_of.rb → at_least_one_of_validator.rb} +0 -2
  47. data/lib/grape/validations/validators/base.rb +7 -0
  48. data/lib/grape/validations/validators/{exactly_one_of.rb → exactly_one_of_validator.rb} +0 -2
  49. data/lib/grape/validations/validators/{mutual_exclusion.rb → mutual_exclusion_validator.rb} +0 -2
  50. data/lib/grape/validations.rb +16 -12
  51. data/lib/grape/version.rb +1 -1
  52. data/lib/grape.rb +74 -28
  53. data/spec/grape/api/custom_validations_spec.rb +41 -2
  54. data/spec/grape/api/deeply_included_options_spec.rb +0 -2
  55. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -2
  56. data/spec/grape/api/documentation_spec.rb +59 -0
  57. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  58. data/spec/grape/api/instance_spec.rb +0 -1
  59. data/spec/grape/api/invalid_format_spec.rb +0 -2
  60. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  61. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  62. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  63. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  64. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  65. data/spec/grape/api/recognize_path_spec.rb +0 -2
  66. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  67. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  68. data/spec/grape/api/routes_with_requirements_spec.rb +0 -2
  69. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -2
  70. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  71. data/spec/grape/api_remount_spec.rb +0 -1
  72. data/spec/grape/api_spec.rb +23 -25
  73. data/spec/grape/config_spec.rb +0 -2
  74. data/spec/grape/dsl/callbacks_spec.rb +0 -2
  75. data/spec/grape/dsl/desc_spec.rb +2 -2
  76. data/spec/grape/dsl/headers_spec.rb +2 -4
  77. data/spec/grape/dsl/helpers_spec.rb +0 -2
  78. data/spec/grape/dsl/inside_route_spec.rb +10 -12
  79. data/spec/grape/dsl/logger_spec.rb +0 -2
  80. data/spec/grape/dsl/middleware_spec.rb +0 -2
  81. data/spec/grape/dsl/parameters_spec.rb +0 -2
  82. data/spec/grape/dsl/request_response_spec.rb +6 -8
  83. data/spec/grape/dsl/routing_spec.rb +1 -3
  84. data/spec/grape/dsl/settings_spec.rb +0 -2
  85. data/spec/grape/dsl/validations_spec.rb +0 -17
  86. data/spec/grape/endpoint/declared_spec.rb +2 -4
  87. data/spec/grape/endpoint_spec.rb +29 -9
  88. data/spec/grape/entity_spec.rb +0 -1
  89. data/spec/grape/exceptions/base_spec.rb +16 -2
  90. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -2
  91. data/spec/grape/exceptions/invalid_accept_header_spec.rb +3 -2
  92. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  93. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  94. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  95. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  96. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  97. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  98. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  99. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  100. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  101. data/spec/grape/exceptions/validation_errors_spec.rb +0 -1
  102. data/spec/grape/exceptions/validation_spec.rb +1 -3
  103. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -2
  104. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -2
  105. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -2
  106. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  107. data/spec/grape/integration/rack_sendfile_spec.rb +0 -2
  108. data/spec/grape/integration/rack_spec.rb +6 -7
  109. data/spec/grape/loading_spec.rb +0 -2
  110. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  111. data/spec/grape/middleware/auth/dsl_spec.rb +0 -2
  112. data/spec/grape/middleware/auth/strategies_spec.rb +0 -2
  113. data/spec/grape/middleware/base_spec.rb +7 -7
  114. data/spec/grape/middleware/error_spec.rb +6 -1
  115. data/spec/grape/middleware/exception_spec.rb +0 -2
  116. data/spec/grape/middleware/formatter_spec.rb +6 -8
  117. data/spec/grape/middleware/globals_spec.rb +0 -2
  118. data/spec/grape/middleware/stack_spec.rb +0 -2
  119. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -2
  120. data/spec/grape/middleware/versioner/header_spec.rb +18 -4
  121. data/spec/grape/middleware/versioner/param_spec.rb +0 -2
  122. data/spec/grape/middleware/versioner/path_spec.rb +0 -2
  123. data/spec/grape/middleware/versioner_spec.rb +0 -2
  124. data/spec/grape/named_api_spec.rb +0 -2
  125. data/spec/grape/parser_spec.rb +0 -2
  126. data/spec/grape/path_spec.rb +0 -2
  127. data/spec/grape/presenters/presenter_spec.rb +0 -2
  128. data/spec/grape/request_spec.rb +0 -2
  129. data/spec/grape/util/inheritable_setting_spec.rb +0 -1
  130. data/spec/grape/util/inheritable_values_spec.rb +0 -1
  131. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -1
  132. data/spec/grape/util/stackable_values_spec.rb +0 -1
  133. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  134. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  135. data/spec/grape/validations/instance_behaivour_spec.rb +0 -2
  136. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -2
  137. data/spec/grape/validations/params_scope_spec.rb +315 -86
  138. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -2
  139. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  140. data/spec/grape/validations/types/primitive_coercer_spec.rb +20 -5
  141. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  142. data/spec/grape/validations/types_spec.rb +28 -2
  143. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -2
  144. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -2
  145. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -2
  146. data/spec/grape/validations/validators/coerce_spec.rb +0 -2
  147. data/spec/grape/validations/validators/default_spec.rb +0 -2
  148. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -2
  149. data/spec/grape/validations/validators/except_values_spec.rb +0 -2
  150. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -2
  151. data/spec/grape/validations/validators/presence_spec.rb +0 -2
  152. data/spec/grape/validations/validators/regexp_spec.rb +0 -2
  153. data/spec/grape/validations/validators/same_as_spec.rb +0 -2
  154. data/spec/grape/validations/validators/values_spec.rb +19 -2
  155. data/spec/grape/validations_spec.rb +78 -27
  156. data/spec/integration/multi_json/json_spec.rb +0 -2
  157. data/spec/integration/multi_xml/xml_spec.rb +0 -2
  158. data/spec/spec_helper.rb +9 -4
  159. metadata +134 -122
  160. data/spec/grape/dsl/configuration_spec.rb +0 -16
  161. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  162. data/spec/support/eager_load.rb +0 -19
  163. /data/lib/grape/validations/validators/{allow_blank.rb → allow_blank_validator.rb} +0 -0
  164. /data/lib/grape/validations/validators/{as.rb → as_validator.rb} +0 -0
  165. /data/lib/grape/validations/validators/{coerce.rb → coerce_validator.rb} +0 -0
  166. /data/lib/grape/validations/validators/{default.rb → default_validator.rb} +0 -0
  167. /data/lib/grape/validations/validators/{except_values.rb → except_values_validator.rb} +0 -0
  168. /data/lib/grape/validations/validators/{presence.rb → presence_validator.rb} +0 -0
  169. /data/lib/grape/validations/validators/{regexp.rb → regexp_validator.rb} +0 -0
  170. /data/lib/grape/validations/validators/{same_as.rb → same_as_validator.rb} +0 -0
  171. /data/lib/grape/validations/validators/{values.rb → values_validator.rb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d182a6dfa2a571345d24a6a2b7286b4a2b34eeedc6570334ba2259fdda59faac
4
- data.tar.gz: c365091e871e7ad78dd46dc0aab52cdd41d1e5ddb5a46503fcf0020af45f4324
3
+ metadata.gz: 40277732454d8810e4e96f638da9e6bd4ab818e39ac9c30788791cb4bd429871
4
+ data.tar.gz: b075dd96ba3dda6fcd05e6b1c126255b5e206b2d6bb9bf9b52f9cd6ec25a6efc
5
5
  SHA512:
6
- metadata.gz: 539fdf761a5058dfcb3bab993a7fac3c7223ec06e0b828e102cb52095ac79f63668ebab1c1c4b47bf16984990c94f9a291537e7b2a1359626736b7abdd2c34ec
7
- data.tar.gz: 2b30d941ab114aab53c4f4630742adedd037856ecc63b65f87b0df506349a13eed092964d9f53c003774006e74b9800043178b2ad2e6c55b0d5d42f6039a7e71
6
+ metadata.gz: 61d1ef36c90927e08119b6abf57b87fc5317b7b4ac73587d14bc23c9b671e0e76930b89b22d15ec806861f2c60c582647a4f95bc6a1100dca07066be1853d4e6
7
+ data.tar.gz: 42a4595d466b2092759dee55ad467a6733e29912b0faaf3abe203c18ab1c84b53b6a1d45868102ac16e6b431254664a6762b3ec0b8e52217c777f99adcf965cc
data/CHANGELOG.md CHANGED
@@ -1,7 +1,60 @@
1
- ### 1.6.2 (2021/12/30)
1
+ ### 1.7.1 (2023/05/14)
2
+
3
+ #### Features
4
+
5
+ * [#2288](https://github.com/ruby-grape/grape/pull/2288): Droped support for Ruby 2.5 - [@ericproulx](https://github.com/ericproulx).
6
+ * [#2288](https://github.com/ruby-grape/grape/pull/2288): Updated rubocop to 1.41.0 - [@ericproulx](https://github.com/ericproulx).
7
+ * [#2296](https://github.com/ruby-grape/grape/pull/2296): Fix cops and enables some - [@ericproulx](https://github.com/ericproulx).
8
+ * [#2302](https://github.com/ruby-grape/grape/pull/2302): Rack < 3 and update rack-test - [@ericproulx](https://github.com/ericproulx).
9
+ * [#2303](https://github.com/ruby-grape/grape/pull/2302): Rack >= 1.3.0 - [@ericproulx](https://github.com/ericproulx).
10
+ * [#2301](https://github.com/ruby-grape/grape/pull/2301): Revisit GH workflows - [@ericproulx](https://github.com/ericproulx).
11
+ * [#2311](https://github.com/ruby-grape/grape/pull/2311): Fix tests by pinning rack-test to < 2.1 - [@duffn](https://github.com/duffn).
12
+ * [#2310](https://github.com/ruby-grape/grape/pull/2310): Fix YARD docs markdown rendering - [@duffn](https://github.com/duffn).
13
+ * [#2317](https://github.com/ruby-grape/grape/pull/2317): Remove maruku and rubocop-ast as direct development/testing dependencies - [@ericproulx](https://github.com/ericproulx).
14
+ * [#2292](https://github.com/ruby-grape/grape/pull/2292): Introduce Docker to local development - [@ericproulx](https://github.com/ericproulx).
15
+ * [#2325](https://github.com/ruby-grape/grape/pull/2325): Change edge test workflows only run on demand - [@dblock](https://github.com/dblock).
16
+ * [#2324](https://github.com/ruby-grape/grape/pull/2324): Expose default in the description dsl - [@dhruvCW](https://github.com/dhruvCW).
17
+
18
+ #### Fixes
19
+
20
+ * [#2299](https://github.com/ruby-grape/grape/pull/2299): Fix, do not use kwargs for empty args - [@dm1try](https://github.com/dm1try).
21
+ * [#2307](https://github.com/ruby-grape/grape/pull/2307): Fixed autoloading of InvalidValue - [@fixlr](https://github.com/fixlr).
22
+ * [#2315](https://github.com/ruby-grape/grape/pull/2315): Update rspec - [@ericproulx](https://github.com/ericproulx).
23
+ * [#2319](https://github.com/ruby-grape/grape/pull/2319): Update rubocop - [@ericproulx](https://github.com/ericproulx).
24
+ * [#2323](https://github.com/ruby-grape/grape/pull/2323): Fix using endless ranges for values parameter - [@dhruvCW](https://github.com/dhruvCW).
25
+
26
+ ### 1.7.0 (2022/12/20)
2
27
 
3
28
  #### Features
4
29
 
30
+ * [#2233](https://github.com/ruby-grape/grape/pull/2233): Added `do_not_document!` for disabling documentation to internal APIs - [@dnesteryuk](https://github.com/dnesteryuk).
31
+ * [#2235](https://github.com/ruby-grape/grape/pull/2235): Add support for Ruby 3.1 - [@petergoldstein](https://github.com/petergoldstein).
32
+ * [#2248](https://github.com/ruby-grape/grape/pull/2248): Upgraded to rspec 3.11.0 - [@dblock](https://github.com/dblock).
33
+ * [#2249](https://github.com/ruby-grape/grape/pull/2249): Split CI matrix, extract edge - [@dblock](https://github.com/dblock).
34
+ * [#2249](https://github.com/ruby-grape/grape/pull/2251): Upgraded to RuboCop 1.25.1 - [@dblock](https://github.com/dblock).
35
+ * [#2271](https://github.com/ruby-grape/grape/pull/2271): Fixed validation regression on Numeric type introduced in 1.3 - [@vasfed](https://github.com/Vasfed).
36
+ * [#2267](https://github.com/ruby-grape/grape/pull/2267): Standardized English error messages - [@dblock](https://github.com/dblock).
37
+ * [#2272](https://github.com/ruby-grape/grape/pull/2272): Added error on param init when provided type does not have `[]` coercion method, previously validation silently failed for any value - [@vasfed](https://github.com/Vasfed).
38
+ * [#2274](https://github.com/ruby-grape/grape/pull/2274): Error middleware support using rack util's symbols as status - [@dhruvCW](https://github.com/dhruvCW).
39
+ * [#2276](https://github.com/ruby-grape/grape/pull/2276): Fix exception super - [@ericproulx](https://github.com/ericproulx).
40
+ * [#2285](https://github.com/ruby-grape/grape/pull/2285), [#2287](https://github.com/ruby-grape/grape/pull/2287): Added :evaluate_given to declared(params) - [@zysend](https://github.com/zysend).
41
+
42
+ #### Fixes
43
+
44
+ * [#2263](https://github.com/ruby-grape/grape/pull/2263): Explicitly require `bigdecimal` and `date` - [@dblock](https://github.com/dblock).
45
+ * [#2222](https://github.com/ruby-grape/grape/pull/2222): Autoload types and validators - [@ericproulx](https://github.com/ericproulx).
46
+ * [#2232](https://github.com/ruby-grape/grape/pull/2232): Fix kwargs support in shared params definition - [@dm1try](https://github.com/dm1try).
47
+ * [#2229](https://github.com/ruby-grape/grape/pull/2229): Do not collect params in route settings - [@dnesteryuk](https://github.com/dnesteryuk).
48
+ * [#2234](https://github.com/ruby-grape/grape/pull/2234): Remove non-UTF8 characters from format before generating JSON error - [@bschmeck](https://github.com/bschmeck).
49
+ * [#2227](https://github.com/ruby-grape/grape/pull/2222): Rename `MissingGroupType` and `UnsupportedGroupType` exceptions - [@ericproulx](https://github.com/ericproulx).
50
+ * [#2244](https://github.com/ruby-grape/grape/pull/2244): Fix a breaking change in `Grape::Validations` provided in 1.6.1 - [@dm1try](https://github.com/dm1try).
51
+ * [#2250](https://github.com/ruby-grape/grape/pull/2250): Add deprecation warning for `UnsupportedGroupTypeError` and `MissingGroupTypeError` - [@ericproulx](https://github.com/ericproulx).
52
+ * [#2256](https://github.com/ruby-grape/grape/pull/2256): Raise `Grape::Exceptions::MultipartPartLimitError` from Rack when too many files are uploaded - [@bschmeck](https://github.com/bschmeck).
53
+ * [#2266](https://github.com/ruby-grape/grape/pull/2266): Fix code coverage - [@duffn](https://github.com/duffn).
54
+ * [#2284](https://github.com/ruby-grape/grape/pull/2284): Fix an unexpected backtick - [@zysend](https://github.com/zysend).
55
+
56
+ ### 1.6.2 (2021/12/30)
57
+
5
58
  #### Fixes
6
59
 
7
60
  * [#2219](https://github.com/ruby-grape/grape/pull/2219): Revert the changes for autoloading provided in 1.6.1 - [@dm1try](https://github.com/dm1try).
data/CONTRIBUTING.md CHANGED
@@ -23,6 +23,34 @@ git pull upstream master
23
23
  git checkout -b my-feature-branch
24
24
  ```
25
25
 
26
+ ### Docker
27
+
28
+ If you're familiar with [Docker](https://www.docker.com/), you can run everything through the following command:
29
+
30
+ ```
31
+ docker-compose run --rm --build grape <command_and_parameters>
32
+ ```
33
+
34
+ About the execution process:
35
+ - displays Ruby, Rubygems, Bundle and Gemfile version when starting:
36
+ ```
37
+ ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux-musl]
38
+ rubygems 3.4.12
39
+ Bundler version 2.4.1 (2022-12-24 commit f3175f033c)
40
+ Running default Gemfile
41
+ ```
42
+ - keeps the gems to the latest possible version
43
+ - executes under `bundle exec`
44
+
45
+ Here are some examples:
46
+
47
+ - running all specs `docker-compose run --rm --build grape rspec`
48
+ - running rspec on a specific file `docker-compose run --rm --build grape rspec spec/:file_path`
49
+ - running task `docker-compose run --rm --build grape rake <task_name>`
50
+ - running rubocop `docker-compose run --rm --build grape rubocop`
51
+ - running all specs on a specific ruby version (e.g 2.7.7) `RUBY_VERSION=2.7.7 docker-compose run --rm --build grape rspec`
52
+ - running specs on a specific gemfile (e.g rails_7_0.gemfile) `docker-compose run -e GEMFILE=rails_7_0 --rm --build grape rspec`
53
+
26
54
  #### Bundle Install and Test
27
55
 
28
56
  Ensure that you can build the project and run tests.
@@ -58,6 +86,8 @@ Make sure that `bundle exec rake` completes without errors.
58
86
 
59
87
  Document any external behavior in the [README](README.md).
60
88
 
89
+ You should also document code as necessary, using current code as examples. This project uses [YARD](https://yardoc.org/). You can run and preview the docs locally by [installing `yard`](https://yardoc.org/), running `yard server --reload` and view the docs at http://localhost:8808.
90
+
61
91
  #### Update Changelog
62
92
 
63
93
  Add a line to [CHANGELOG](CHANGELOG.md) under *Next Release*. Make it look like every other line, including your name and link to your Github account.
data/README.md CHANGED
@@ -40,6 +40,7 @@
40
40
  - [Declared](#declared)
41
41
  - [Include Parent Namespaces](#include-parent-namespaces)
42
42
  - [Include Missing](#include-missing)
43
+ - [Evaluate Given](#evaluate-given)
43
44
  - [Parameter Validation and Coercion](#parameter-validation-and-coercion)
44
45
  - [Supported Parameter Types](#supported-parameter-types)
45
46
  - [Integer/Fixnum and Coercions](#integerfixnum-and-coercions)
@@ -158,7 +159,7 @@ content negotiation, versioning and much more.
158
159
 
159
160
  ## Stable Release
160
161
 
161
- You're reading the documentation for the stable release of Grape, **1.6.2**.
162
+ You're reading the documentation for the stable release of Grape, 1.7.1.
162
163
  Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
163
164
 
164
165
  ## Project Resources
@@ -174,21 +175,13 @@ Available as part of the Tidelift Subscription.
174
175
 
175
176
  The maintainers of Grape are working with Tidelift to deliver commercial support and maintenance. Save time, reduce risk, and improve code health, while paying the maintainers of Grape. Click [here](https://tidelift.com/subscription/request-a-demo?utm_source=rubygems-grape&utm_medium=referral&utm_campaign=enterprise) for more details.
176
177
 
177
- In 2020, we plan to use the money towards gathering Grape contributors for dinner in New York City.
178
-
179
178
  ## Installation
180
179
 
181
180
  Ruby 2.4 or newer is required.
182
181
 
183
- Grape is available as a gem, to install it just install the gem:
184
-
185
- gem install grape
186
-
187
- If you're using Bundler, add the gem to Gemfile.
182
+ Grape is available as a gem, to install it run:
188
183
 
189
- gem 'grape'
190
-
191
- Run `bundle install`.
184
+ bundle add grape
192
185
 
193
186
  ## Basic Usage
194
187
 
@@ -545,12 +538,12 @@ end
545
538
 
546
539
  class V1 < Grape::API
547
540
  version 'v1'
548
- mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Enitities::Status } }
541
+ mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Entities::Status } }
549
542
  end
550
543
 
551
544
  class V2 < Grape::API
552
545
  version 'v2'
553
- mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Enitities::V2::Status } }
546
+ mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Entities::V2::Status } }
554
547
  end
555
548
  ```
556
549
 
@@ -645,6 +638,7 @@ desc 'Returns your public timeline.' do
645
638
  params API::Entities::Status.documentation
646
639
  success API::Entities::Entity
647
640
  failure [[401, 'Unauthorized', 'Entities::Error']]
641
+ default { code: 500, message: 'InvalidRequest', model: Entities::Error }
648
642
  named 'My named route'
649
643
  headers XAuthToken: {
650
644
  description: 'Validates your identity',
@@ -669,8 +663,9 @@ end
669
663
 
670
664
  * `detail`: A more enhanced description
671
665
  * `params`: Define parameters directly from an `Entity`
672
- * `success`: (former entity) The `Entity` to be used to present by default this route
673
- * `failure`: (former http_codes) A definition of the used failure HTTP Codes and Entities
666
+ * `success`: (former entity) The `Entity` to be used to present the success response for this route.
667
+ * `failure`: (former http_codes) A definition of the used failure HTTP Codes and Entities.
668
+ * `default`: The definition and `Entity` used to present the default response for this route.
674
669
  * `named`: A helper to give a route a name and find it with this name in the documentation Hash
675
670
  * `headers`: A definition of the used Headers
676
671
  * Other options can be found in [grape-swagger][grape-swagger]
@@ -1085,6 +1080,102 @@ curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d
1085
1080
  }
1086
1081
  ````
1087
1082
 
1083
+ ### Evaluate Given
1084
+
1085
+ By default `declared(params)` will not evaluate `given` and return all parameters. Use `evaluate_given` to evaluate all `given` blocks and return only parameters that satisfy `given` conditions. Consider the following API:
1086
+
1087
+ ````ruby
1088
+ format :json
1089
+
1090
+ params do
1091
+ optional :child_id, type: Integer
1092
+ given :child_id do
1093
+ requires :father_id, type: Integer
1094
+ end
1095
+ end
1096
+
1097
+ post 'child' do
1098
+ { 'declared_params' => declared(params, evaluate_given: true) }
1099
+ end
1100
+ ````
1101
+
1102
+ **Request**
1103
+
1104
+ ````bash
1105
+ curl -X POST -H "Content-Type: application/json" localhost:9292/child -d '{"father_id": 1}'
1106
+ ````
1107
+
1108
+ **Response with evaluate_given:false**
1109
+
1110
+ ````json
1111
+ {
1112
+ "declared_params": {
1113
+ "child_id": null,
1114
+ "father_id": 1
1115
+ }
1116
+ }
1117
+ ````
1118
+
1119
+ **Response with evaluate_given:true**
1120
+
1121
+ ````json
1122
+ {
1123
+ "declared_params": {
1124
+ "child_id": null
1125
+ }
1126
+ }
1127
+ ````
1128
+
1129
+ It also works on nested hashes:
1130
+
1131
+ ````ruby
1132
+ format :json
1133
+
1134
+ params do
1135
+ requires :child, type: Hash do
1136
+ optional :child_id, type: Integer
1137
+ given :child_id do
1138
+ requires :father_id, type: Integer
1139
+ end
1140
+ end
1141
+ end
1142
+
1143
+ post 'child' do
1144
+ { 'declared_params' => declared(params, evaluate_given: true) }
1145
+ end
1146
+ ````
1147
+
1148
+ **Request**
1149
+
1150
+ ````bash
1151
+ curl -X POST -H "Content-Type: application/json" localhost:9292/child -d '{"child": {"father_id": 1}}'
1152
+ ````
1153
+
1154
+ **Response with evaluate_given:false**
1155
+
1156
+ ````json
1157
+ {
1158
+ "declared_params": {
1159
+ "child": {
1160
+ "child_id": null,
1161
+ "father_id": 1
1162
+ }
1163
+ }
1164
+ }
1165
+ ````
1166
+
1167
+ **Response with evaluate_given:true**
1168
+
1169
+ ````json
1170
+ {
1171
+ "declared_params": {
1172
+ "child": {
1173
+ "child_id": null
1174
+ }
1175
+ }
1176
+ }
1177
+ ````
1178
+
1088
1179
  ## Parameter Validation and Coercion
1089
1180
 
1090
1181
  You can define validations and coercion options for your parameters using a `params` block.
@@ -1453,7 +1544,7 @@ resource :users do
1453
1544
  end
1454
1545
  ```
1455
1546
 
1456
- The value passed to `as` will be the key when calling `params` or `declared(params)`.
1547
+ The value passed to `as` will be the key when calling `declared(params)`.
1457
1548
 
1458
1549
  ### Built-in Validators
1459
1550
 
@@ -1497,6 +1588,15 @@ params do
1497
1588
  end
1498
1589
  ```
1499
1590
 
1591
+ Note endless ranges are also supported with ActiveSupport >= 6.0, but they require that the type be provided.
1592
+
1593
+ ```ruby
1594
+ params do
1595
+ requires :minimum, type: Integer, values: 10..
1596
+ optional :maximum, type: Integer, values: ..10
1597
+ end
1598
+ ```
1599
+
1500
1600
  Note that *both* range endpoints have to be a `#kind_of?` your `:type` option (if you don't supply the `:type` option, it will be guessed to be equal to the class of the range's first endpoint). So the following is invalid:
1501
1601
 
1502
1602
  ```ruby
@@ -1742,10 +1842,10 @@ end
1742
1842
  ### Custom Validators
1743
1843
 
1744
1844
  ```ruby
1745
- class AlphaNumeric < Grape::Validations::Base
1845
+ class AlphaNumeric < Grape::Validations::Validators::Base
1746
1846
  def validate_param!(attr_name, params)
1747
1847
  unless params[attr_name] =~ /\A[[:alnum:]]+\z/
1748
- fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: 'must consist of alpha-numeric characters'
1848
+ raise Grape::Exceptions::Validation.new params: [@scope.full_name(attr_name)], message: 'must consist of alpha-numeric characters'
1749
1849
  end
1750
1850
  end
1751
1851
  end
@@ -1760,10 +1860,10 @@ end
1760
1860
  You can also create custom classes that take parameters.
1761
1861
 
1762
1862
  ```ruby
1763
- class Length < Grape::Validations::Base
1863
+ class Length < Grape::Validations::Validators::Base
1764
1864
  def validate_param!(attr_name, params)
1765
1865
  unless params[attr_name].length <= @option
1766
- fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long"
1866
+ raise Grape::Exceptions::Validation.new params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long"
1767
1867
  end
1768
1868
  end
1769
1869
  end
@@ -1778,7 +1878,7 @@ end
1778
1878
  You can also create custom validation that use request to validate the attribute. For example if you want to have parameters that are available to only admins, you can do the following.
1779
1879
 
1780
1880
  ```ruby
1781
- class Admin < Grape::Validations::Base
1881
+ class Admin < Grape::Validations::Validators::Base
1782
1882
  def validate(request)
1783
1883
  # return if the param we are checking was not in request
1784
1884
  # @attrs is a list containing the attribute we are currently validating
@@ -1789,7 +1889,7 @@ class Admin < Grape::Validations::Base
1789
1889
  return unless @option
1790
1890
  # check if user is admin or not
1791
1891
  # as an example get a token from request and check if it's admin or not
1792
- fail Grape::Exceptions::Validation, params: @attrs, message: 'Can not set admin-only field.' unless request.headers['X-Access-Token'] == 'admin'
1892
+ raise Grape::Exceptions::Validation.new params: @attrs, message: 'Can not set admin-only field.' unless request.headers['X-Access-Token'] == 'admin'
1793
1893
  end
1794
1894
  end
1795
1895
  ```
@@ -2248,6 +2348,18 @@ params do
2248
2348
  end
2249
2349
  ```
2250
2350
 
2351
+ If documentation isn't needed (for instance, it is an internal API), documentation can be disabled.
2352
+
2353
+ ```ruby
2354
+ class API < Grape::API
2355
+ do_not_document!
2356
+
2357
+ # endpoints...
2358
+ end
2359
+ ```
2360
+
2361
+ In this case, Grape won't create objects related to documentation which are retained in RAM forever.
2362
+
2251
2363
  ## Cookies
2252
2364
 
2253
2365
  You can set, get and delete your cookies very simply using `cookies` method.
@@ -3239,6 +3351,17 @@ end
3239
3351
 
3240
3352
  Use `body false` to return `204 No Content` without any data or content-type.
3241
3353
 
3354
+ If you want to empty the body with an HTTP status code other than `204 No Content`, you can override the status code after specifying `body false` as follows
3355
+
3356
+ ```ruby
3357
+ class API < Grape::API
3358
+ get '/' do
3359
+ body false
3360
+ status 304
3361
+ end
3362
+ end
3363
+ ```
3364
+
3242
3365
  You can also set the response to a file with `sendfile`. This works with the
3243
3366
  [Rack::Sendfile](https://www.rubydoc.info/gems/rack/Rack/Sendfile) middleware to optimally send
3244
3367
  the file through your web server software.
@@ -3701,7 +3824,7 @@ Use `rack-test` and define your API as `app`.
3701
3824
  You can test a Grape API with RSpec by making HTTP requests and examining the response.
3702
3825
 
3703
3826
  ```ruby
3704
- require 'spec_helper'
3827
+
3705
3828
 
3706
3829
  describe Twitter::API do
3707
3830
  include Rack::Test::Methods
data/UPGRADING.md CHANGED
@@ -1,6 +1,21 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 1.7.0
5
+
6
+ #### Exceptions renaming
7
+
8
+ The following exceptions has been renamed for consistency through exceptions naming :
9
+
10
+ * `MissingGroupTypeError` => `MissingGroupType`
11
+ * `UnsupportedGroupTypeError` => `UnsupportedGroupType`
12
+
13
+ See [#2227](https://github.com/ruby-grape/grape/pull/2227) for more information.
14
+
15
+ #### Handling Multipart Limit Errors
16
+
17
+ Rack supports a configurable limit on the number of files created from multipart parameters (`Rack::Utils.multipart_part_limit`) and raises an error if params are received that create too many files. If you were handling the Rack error directly, Grape now wraps that error in `Grape::Execeptions::TooManyMultipartFiles`. Additionally, Grape will return a 413 status code if the exception goes unhandled.
18
+
4
19
  ### Upgrading to >= 1.6.0
5
20
 
6
21
  #### Parameter renaming with :as
data/grape.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_runtime_dependency 'builder'
25
25
  s.add_runtime_dependency 'dry-types', '>= 1.1'
26
26
  s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
27
- s.add_runtime_dependency 'rack', '>= 1.3.0'
27
+ s.add_runtime_dependency 'rack', '>= 1.3.0', '< 3'
28
28
  s.add_runtime_dependency 'rack-accept'
29
29
 
30
30
  s.files = %w[CHANGELOG.md CONTRIBUTING.md README.md grape.png UPGRADING.md LICENSE]
@@ -32,5 +32,5 @@ Gem::Specification.new do |s|
32
32
  s.files += Dir['lib/**/*']
33
33
  s.test_files = Dir['spec/**/*']
34
34
  s.require_paths = ['lib']
35
- s.required_ruby_version = '>= 2.5.0'
35
+ s.required_ruby_version = '>= 2.6.0'
36
36
  end
@@ -101,7 +101,7 @@ module Grape
101
101
  # block passed in. Allows for simple 'before' setups
102
102
  # of settings stack pushes.
103
103
  def nest(*blocks, &block)
104
- blocks.reject!(&:nil?)
104
+ blocks.compact!
105
105
  if blocks.any?
106
106
  evaluate_as_instance_with_configuration(block) if block
107
107
  blocks.each { |b| evaluate_as_instance_with_configuration(b) }
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-types'
4
+
5
+ module Grape
6
+ module DryTypes
7
+ # Call +Dry.Types()+ to add all registered types to +DryTypes+ which is
8
+ # a container in this case. Check documentation for more information
9
+ # https://dry-rb.org/gems/dry-types/1.2/getting-started/
10
+ include Dry.Types()
11
+ end
12
+ end
data/lib/grape/dsl/api.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module API
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  # Blocks can be executed before or after every API call, using `before`, `after`,
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module Configuration
@@ -78,21 +78,6 @@ module Grape
78
78
  route_setting :description, options
79
79
  end
80
80
 
81
- def description_field(field, value = nil)
82
- description = route_setting(:description)
83
- if value
84
- description ||= route_setting(:description, {})
85
- description[field] = value
86
- elsif description
87
- description[field]
88
- end
89
- end
90
-
91
- def unset_description_field(field)
92
- description = route_setting(:description)
93
- description&.delete(field)
94
- end
95
-
96
81
  # Returns an object which configures itself via an instance-context DSL.
97
82
  def desc_container(endpoint_configuration)
98
83
  Module.new do
@@ -113,7 +98,8 @@ module Grape
113
98
  :produces,
114
99
  :consumes,
115
100
  :security,
116
- :tags
101
+ :tags,
102
+ :default
117
103
  )
118
104
  config_context.define_singleton_method(:configuration) do
119
105
  endpoint_configuration
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module Helpers
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
3
  require 'grape/dsl/headers'
5
4
 
6
5
  module Grape
@@ -29,7 +28,7 @@ module Grape
29
28
  # has completed
30
29
  module PostBeforeFilter
31
30
  def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
32
- options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
31
+ options = options.reverse_merge(include_missing: true, include_parent_namespaces: true, evaluate_given: false)
33
32
  declared_params ||= optioned_declared_params(**options)
34
33
 
35
34
  if passed_params.is_a?(Array)
@@ -48,41 +47,46 @@ module Grape
48
47
  end
49
48
 
50
49
  def declared_hash(passed_params, options, declared_params, params_nested_path)
51
- renamed_params = route_setting(:renamed_params) || {}
50
+ declared_params.each_with_object(passed_params.class.new) do |declared_param_attr, memo|
51
+ next if options[:evaluate_given] && !declared_param_attr.scope.attr_meets_dependency?(passed_params)
52
52
 
53
- declared_params.each_with_object(passed_params.class.new) do |declared_param, memo|
54
- if declared_param.is_a?(Hash)
55
- declared_param.each_pair do |declared_parent_param, declared_children_params|
56
- params_nested_path_dup = params_nested_path.dup
57
- params_nested_path_dup << declared_parent_param.to_s
58
- next unless options[:include_missing] || passed_params.key?(declared_parent_param)
53
+ declared_hash_attr(passed_params, options, declared_param_attr.key, params_nested_path, memo)
54
+ end
55
+ end
59
56
 
60
- rename_path = params_nested_path + [declared_parent_param.to_s]
61
- renamed_param_name = renamed_params[rename_path]
57
+ def declared_hash_attr(passed_params, options, declared_param, params_nested_path, memo)
58
+ renamed_params = route_setting(:renamed_params) || {}
59
+ if declared_param.is_a?(Hash)
60
+ declared_param.each_pair do |declared_parent_param, declared_children_params|
61
+ params_nested_path_dup = params_nested_path.dup
62
+ params_nested_path_dup << declared_parent_param.to_s
63
+ next unless options[:include_missing] || passed_params.key?(declared_parent_param)
64
+
65
+ rename_path = params_nested_path + [declared_parent_param.to_s]
66
+ renamed_param_name = renamed_params[rename_path]
62
67
 
63
- memo_key = optioned_param_key(renamed_param_name || declared_parent_param, options)
64
- passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
68
+ memo_key = optioned_param_key(renamed_param_name || declared_parent_param, options)
69
+ passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
65
70
 
66
- memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
67
- declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
68
- end
71
+ memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
72
+ declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
69
73
  end
70
- else
71
- # If it is not a Hash then it does not have children.
72
- # Find its value or set it to nil.
73
- next unless options[:include_missing] || passed_params.key?(declared_param)
74
+ end
75
+ else
76
+ # If it is not a Hash then it does not have children.
77
+ # Find its value or set it to nil.
78
+ return unless options[:include_missing] || passed_params.key?(declared_param)
74
79
 
75
- rename_path = params_nested_path + [declared_param.to_s]
76
- renamed_param_name = renamed_params[rename_path]
80
+ rename_path = params_nested_path + [declared_param.to_s]
81
+ renamed_param_name = renamed_params[rename_path]
77
82
 
78
- memo_key = optioned_param_key(renamed_param_name || declared_param, options)
79
- passed_param = passed_params[declared_param]
83
+ memo_key = optioned_param_key(renamed_param_name || declared_param, options)
84
+ passed_param = passed_params[declared_param]
80
85
 
81
- params_nested_path_dup = params_nested_path.dup
82
- params_nested_path_dup << declared_param.to_s
83
- memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
84
- passed_param
85
- end
86
+ params_nested_path_dup = params_nested_path.dup
87
+ params_nested_path_dup << declared_param.to_s
88
+ memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
89
+ passed_param
86
90
  end
87
91
  end
88
92
  end
@@ -91,7 +95,7 @@ module Grape
91
95
  return yield if has_passed_children
92
96
 
93
97
  key = params_nested_path[0]
94
- key += "[#{params_nested_path[1..-1].join('][')}]" if params_nested_path.size > 1
98
+ key += "[#{params_nested_path[1..].join('][')}]" if params_nested_path.size > 1
95
99
 
96
100
  route_options_params = options[:route_options][:params] || {}
97
101
  type = route_options_params.dig(key, :type)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/concern'
4
-
5
3
  module Grape
6
4
  module DSL
7
5
  module Middleware