grape 1.5.2 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +152 -21
  5. data/UPGRADING.md +86 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +2 -19
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +8 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +21 -36
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +2 -2
  28. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  29. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  30. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  31. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  32. data/lib/grape/exceptions/validation.rb +1 -6
  33. data/lib/grape/formatter/json.rb +1 -0
  34. data/lib/grape/formatter/serializable_hash.rb +2 -1
  35. data/lib/grape/formatter/xml.rb +1 -0
  36. data/lib/grape/locale/en.yml +9 -8
  37. data/lib/grape/middleware/auth/dsl.rb +7 -2
  38. data/lib/grape/middleware/base.rb +3 -1
  39. data/lib/grape/middleware/error.rb +2 -2
  40. data/lib/grape/middleware/formatter.rb +4 -4
  41. data/lib/grape/middleware/stack.rb +2 -2
  42. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  43. data/lib/grape/middleware/versioner/header.rb +6 -4
  44. data/lib/grape/middleware/versioner/param.rb +1 -0
  45. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  46. data/lib/grape/middleware/versioner/path.rb +2 -0
  47. data/lib/grape/parser/json.rb +1 -1
  48. data/lib/grape/parser/xml.rb +1 -1
  49. data/lib/grape/path.rb +1 -0
  50. data/lib/grape/request.rb +5 -0
  51. data/lib/grape/router/pattern.rb +1 -1
  52. data/lib/grape/router/route.rb +2 -2
  53. data/lib/grape/router.rb +6 -0
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +137 -78
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/json.rb +2 -1
  64. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  65. data/lib/grape/validations/types/set_coercer.rb +0 -2
  66. data/lib/grape/validations/types.rb +98 -30
  67. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  68. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  69. data/lib/grape/validations/validators/as_validator.rb +14 -0
  70. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  71. data/lib/grape/validations/validators/base.rb +82 -70
  72. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  73. data/lib/grape/validations/validators/default_validator.rb +51 -0
  74. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  75. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  76. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  77. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  78. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  79. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  80. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  81. data/lib/grape/validations/validators/values_validator.rb +88 -0
  82. data/lib/grape/validations.rb +16 -6
  83. data/lib/grape/version.rb +1 -1
  84. data/lib/grape.rb +70 -29
  85. data/spec/grape/api/custom_validations_spec.rb +116 -45
  86. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  87. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  88. data/spec/grape/api/documentation_spec.rb +59 -0
  89. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  90. data/spec/grape/api/instance_spec.rb +0 -1
  91. data/spec/grape/api/invalid_format_spec.rb +2 -2
  92. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  93. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  94. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  95. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  96. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  97. data/spec/grape/api/recognize_path_spec.rb +1 -3
  98. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  99. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  100. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  101. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  102. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  103. data/spec/grape/api_remount_spec.rb +16 -16
  104. data/spec/grape/api_spec.rb +527 -224
  105. data/spec/grape/config_spec.rb +0 -2
  106. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  107. data/spec/grape/dsl/configuration_spec.rb +0 -2
  108. data/spec/grape/dsl/desc_spec.rb +0 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +98 -57
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +0 -2
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +24 -17
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +27 -8
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
  169. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  170. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  171. data/spec/grape/validations/params_scope_spec.rb +361 -96
  172. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  173. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  174. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  175. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  176. data/spec/grape/validations/types_spec.rb +36 -10
  177. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  178. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  179. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  180. data/spec/grape/validations/validators/coerce_spec.rb +99 -24
  181. data/spec/grape/validations/validators/default_spec.rb +72 -80
  182. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  183. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  184. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  185. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  186. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  187. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  188. data/spec/grape/validations/validators/values_spec.rb +182 -179
  189. data/spec/grape/validations_spec.rb +149 -80
  190. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  191. data/spec/integration/multi_json/json_spec.rb +1 -3
  192. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  193. data/spec/shared/versioning_examples.rb +12 -9
  194. data/spec/spec_helper.rb +21 -6
  195. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  196. metadata +125 -115
  197. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  198. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  199. data/lib/grape/validations/validators/as.rb +0 -16
  200. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  201. data/lib/grape/validations/validators/coerce.rb +0 -91
  202. data/lib/grape/validations/validators/default.rb +0 -48
  203. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  204. data/lib/grape/validations/validators/except_values.rb +0 -22
  205. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  206. data/lib/grape/validations/validators/presence.rb +0 -12
  207. data/lib/grape/validations/validators/regexp.rb +0 -13
  208. data/lib/grape/validations/validators/same_as.rb +0 -26
  209. data/lib/grape/validations/validators/values.rb +0 -83
  210. data/spec/support/eager_load.rb +0 -19
@@ -1,74 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
- describe Grape::Validations::AtLeastOneOfValidator do
6
- describe '#validate!' do
7
- subject(:validate) { post path, params }
8
-
9
- module ValidationsSpec
10
- module AtLeastOneOfValidatorSpec
11
- class API < Grape::API
12
- rescue_from Grape::Exceptions::ValidationErrors do |e|
13
- error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
14
- end
3
+ describe Grape::Validations::Validators::AtLeastOneOfValidator do
4
+ let_it_be(:app) do
5
+ Class.new(Grape::API) do
6
+ rescue_from Grape::Exceptions::ValidationErrors do |e|
7
+ error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
8
+ end
15
9
 
16
- params do
17
- optional :beer, :wine, :grapefruit
18
- at_least_one_of :beer, :wine, :grapefruit
19
- end
20
- post do
21
- end
10
+ params do
11
+ optional :beer, :wine, :grapefruit
12
+ at_least_one_of :beer, :wine, :grapefruit
13
+ end
14
+ post do
15
+ end
22
16
 
23
- params do
24
- optional :beer, :wine, :grapefruit, :other
25
- at_least_one_of :beer, :wine, :grapefruit
26
- end
27
- post 'mixed-params' do
28
- end
17
+ params do
18
+ optional :beer, :wine, :grapefruit, :other
19
+ at_least_one_of :beer, :wine, :grapefruit
20
+ end
21
+ post 'mixed-params' do
22
+ end
29
23
 
30
- params do
31
- optional :beer, :wine, :grapefruit
32
- at_least_one_of :beer, :wine, :grapefruit, message: 'you should choose something'
33
- end
34
- post '/custom-message' do
35
- end
24
+ params do
25
+ optional :beer, :wine, :grapefruit
26
+ at_least_one_of :beer, :wine, :grapefruit, message: 'you should choose something'
27
+ end
28
+ post '/custom-message' do
29
+ end
36
30
 
37
- params do
38
- requires :item, type: Hash do
39
- optional :beer, :wine, :grapefruit
40
- at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
41
- end
42
- end
43
- post '/nested-hash' do
44
- end
31
+ params do
32
+ requires :item, type: Hash do
33
+ optional :beer, :wine, :grapefruit
34
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
35
+ end
36
+ end
37
+ post '/nested-hash' do
38
+ end
45
39
 
46
- params do
47
- requires :items, type: Array do
48
- optional :beer, :wine, :grapefruit
49
- at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
50
- end
51
- end
52
- post '/nested-array' do
53
- end
40
+ params do
41
+ requires :items, type: Array do
42
+ optional :beer, :wine, :grapefruit
43
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
44
+ end
45
+ end
46
+ post '/nested-array' do
47
+ end
54
48
 
55
- params do
56
- requires :items, type: Array do
57
- requires :nested_items, type: Array do
58
- optional :beer, :wine, :grapefruit
59
- at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
60
- end
61
- end
62
- end
63
- post '/deeply-nested-array' do
49
+ params do
50
+ requires :items, type: Array do
51
+ requires :nested_items, type: Array do
52
+ optional :beer, :wine, :grapefruit
53
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
64
54
  end
65
55
  end
66
56
  end
57
+ post '/deeply-nested-array' do
58
+ end
67
59
  end
60
+ end
68
61
 
69
- def app
70
- ValidationsSpec::AtLeastOneOfValidatorSpec::API
71
- end
62
+ describe '#validate!' do
63
+ subject(:validate) { post path, params }
72
64
 
73
65
  context 'when all restricted params are present' do
74
66
  let(:path) { '/' }
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
- describe Grape::Validations::CoerceValidator do
3
+ describe Grape::Validations::Validators::CoerceValidator do
6
4
  subject do
7
5
  Class.new(Grape::API)
8
6
  end
@@ -23,7 +21,7 @@ describe Grape::Validations::CoerceValidator do
23
21
  end
24
22
 
25
23
  context 'i18n' do
26
- after :each do
24
+ after do
27
25
  I18n.available_locales = %i[en]
28
26
  I18n.locale = :en
29
27
  I18n.default_locale = :en
@@ -31,9 +29,9 @@ describe Grape::Validations::CoerceValidator do
31
29
 
32
30
  it 'i18n error on malformed input' do
33
31
  I18n.available_locales = %i[en zh-CN]
34
- I18n.load_path << File.expand_path('../zh-CN.yml', __FILE__)
32
+ I18n.load_path << File.expand_path('zh-CN.yml', __dir__)
35
33
  I18n.reload!
36
- I18n.locale = 'zh-CN'.to_sym
34
+ I18n.locale = :'zh-CN'
37
35
  subject.params do
38
36
  requires :age, type: Integer
39
37
  end
@@ -48,7 +46,7 @@ describe Grape::Validations::CoerceValidator do
48
46
 
49
47
  it 'gives an english fallback error when default locale message is blank' do
50
48
  I18n.available_locales = %i[en pt-BR]
51
- I18n.locale = 'pt-BR'.to_sym
49
+ I18n.locale = :'pt-BR'
52
50
  subject.params do
53
51
  requires :age, type: Integer
54
52
  end
@@ -83,10 +81,11 @@ describe Grape::Validations::CoerceValidator do
83
81
  context 'on custom coercion rules' do
84
82
  before do
85
83
  subject.params do
86
- requires :a, types: { value: [Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
87
- if val == 'yup'
84
+ requires :a, types: { value: [Grape::API::Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
85
+ case val
86
+ when 'yup'
88
87
  true
89
- elsif val == 'false'
88
+ when 'false'
90
89
  0
91
90
  else
92
91
  val
@@ -170,9 +169,9 @@ describe Grape::Validations::CoerceValidator do
170
169
  expect(last_response.body).to eq('BigDecimal 45.1')
171
170
  end
172
171
 
173
- it 'Boolean' do
172
+ it 'Grape::API::Boolean' do
174
173
  subject.params do
175
- requires :boolean, type: Boolean
174
+ requires :boolean, type: Grape::API::Boolean
176
175
  end
177
176
  subject.post '/boolean' do
178
177
  params[:boolean]
@@ -369,9 +368,9 @@ describe Grape::Validations::CoerceValidator do
369
368
  end
370
369
  end
371
370
 
372
- it 'Boolean' do
371
+ it 'Grape::API::Boolean' do
373
372
  subject.params do
374
- requires :boolean, type: Boolean
373
+ requires :boolean, type: Grape::API::Boolean
375
374
  end
376
375
  subject.get '/boolean' do
377
376
  params[:boolean].class
@@ -650,7 +649,7 @@ describe Grape::Validations::CoerceValidator do
650
649
 
651
650
  it 'parses parameters with Array[Array[String]] type and coerce_with' do
652
651
  subject.params do
653
- requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(/,/).map(&:strip)] : val }
652
+ requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(',').map(&:strip)] : val }
654
653
  end
655
654
  subject.post '/coerce_nested_strings' do
656
655
  params[:values]
@@ -706,6 +705,44 @@ describe Grape::Validations::CoerceValidator do
706
705
  expect(JSON.parse(last_response.body)).to eq([1, 1, 1, 1])
707
706
  end
708
707
 
708
+ context 'Array type and coerce_with should' do
709
+ before do
710
+ subject.params do
711
+ optional :arr, type: Array, coerce_with: (lambda do |val|
712
+ if val.nil?
713
+ []
714
+ else
715
+ val
716
+ end
717
+ end)
718
+ end
719
+ subject.get '/' do
720
+ params[:arr].class.to_s
721
+ end
722
+ end
723
+
724
+ it 'coerce nil value to array' do
725
+ get '/', arr: nil
726
+
727
+ expect(last_response.status).to eq(200)
728
+ expect(last_response.body).to eq('Array')
729
+ end
730
+
731
+ it 'not coerce missing field' do
732
+ get '/'
733
+
734
+ expect(last_response.status).to eq(200)
735
+ expect(last_response.body).to eq('NilClass')
736
+ end
737
+
738
+ it 'coerce array as array' do
739
+ get '/', arr: []
740
+
741
+ expect(last_response.status).to eq(200)
742
+ expect(last_response.body).to eq('Array')
743
+ end
744
+ end
745
+
709
746
  it 'uses parse where available' do
710
747
  subject.params do
711
748
  requires :ints, type: Array, coerce_with: JSON do
@@ -754,13 +791,52 @@ describe Grape::Validations::CoerceValidator do
754
791
  expect(last_response.body).to eq('3')
755
792
  end
756
793
 
794
+ context 'Integer type and coerce_with should' do
795
+ before do
796
+ subject.params do
797
+ optional :int, type: Integer, coerce_with: (lambda do |val|
798
+ if val.nil?
799
+ 0
800
+ else
801
+ val.to_i
802
+ end
803
+ end)
804
+ end
805
+ subject.get '/' do
806
+ params[:int].class.to_s
807
+ end
808
+ end
809
+
810
+ it 'coerce nil value to integer' do
811
+ get '/', int: nil
812
+
813
+ expect(last_response.status).to eq(200)
814
+ expect(last_response.body).to eq('Integer')
815
+ end
816
+
817
+ it 'not coerce missing field' do
818
+ get '/'
819
+
820
+ expect(last_response.status).to eq(200)
821
+ expect(last_response.body).to eq('NilClass')
822
+ end
823
+
824
+ it 'coerce integer as integer' do
825
+ get '/', int: 1
826
+
827
+ expect(last_response.status).to eq(200)
828
+ expect(last_response.body).to eq('Integer')
829
+ end
830
+ end
831
+
757
832
  context 'Integer type and coerce_with potentially returning nil' do
758
833
  before do
759
834
  subject.params do
760
835
  requires :int, type: Integer, coerce_with: (lambda do |val|
761
- if val == '0'
836
+ case val
837
+ when '0'
762
838
  nil
763
- elsif val.match?(/^-?\d+$/)
839
+ when /^-?\d+$/
764
840
  val.to_i
765
841
  else
766
842
  val
@@ -940,11 +1016,9 @@ describe Grape::Validations::CoerceValidator do
940
1016
  end
941
1017
 
942
1018
  context 'multiple types' do
943
- Boolean = Grape::API::Boolean
944
-
945
1019
  it 'coerces to first possible type' do
946
1020
  subject.params do
947
- requires :a, types: [Boolean, Integer, String]
1021
+ requires :a, types: [Grape::API::Boolean, Integer, String]
948
1022
  end
949
1023
  subject.get '/' do
950
1024
  params[:a].class.to_s
@@ -965,7 +1039,7 @@ describe Grape::Validations::CoerceValidator do
965
1039
 
966
1040
  it 'fails when no coercion is possible' do
967
1041
  subject.params do
968
- requires :a, types: [Boolean, Integer]
1042
+ requires :a, types: [Grape::API::Boolean, Integer]
969
1043
  end
970
1044
  subject.get '/' do
971
1045
  params[:a].class.to_s
@@ -1124,10 +1198,11 @@ describe Grape::Validations::CoerceValidator do
1124
1198
  context 'custom coercion rules' do
1125
1199
  before do
1126
1200
  subject.params do
1127
- requires :a, types: [Boolean, String], coerce_with: (lambda do |val|
1128
- if val == 'yup'
1201
+ requires :a, types: [Grape::API::Boolean, String], coerce_with: (lambda do |val|
1202
+ case val
1203
+ when 'yup'
1129
1204
  true
1130
- elsif val == 'false'
1205
+ when 'false'
1131
1206
  0
1132
1207
  else
1133
1208
  val
@@ -1,105 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
- describe Grape::Validations::DefaultValidator do
6
- module ValidationsSpec
7
- module DefaultValidatorSpec
8
- class API < Grape::API
9
- default_format :json
10
-
11
- params do
12
- optional :id
13
- optional :type, default: 'default-type'
14
- end
15
- get '/' do
16
- { id: params[:id], type: params[:type] }
17
- end
3
+ describe Grape::Validations::Validators::DefaultValidator do
4
+ let_it_be(:app) do
5
+ Class.new(Grape::API) do
6
+ default_format :json
7
+
8
+ params do
9
+ optional :id
10
+ optional :type, default: 'default-type'
11
+ end
12
+ get '/' do
13
+ { id: params[:id], type: params[:type] }
14
+ end
18
15
 
19
- params do
20
- optional :type1, default: 'default-type1'
21
- optional :type2, default: 'default-type2'
22
- end
23
- get '/user' do
24
- { type1: params[:type1], type2: params[:type2] }
25
- end
16
+ params do
17
+ optional :type1, default: 'default-type1'
18
+ optional :type2, default: 'default-type2'
19
+ end
20
+ get '/user' do
21
+ { type1: params[:type1], type2: params[:type2] }
22
+ end
26
23
 
27
- params do
28
- requires :id
29
- optional :type1, default: 'default-type1'
30
- optional :type2, default: 'default-type2'
31
- end
24
+ params do
25
+ requires :id
26
+ optional :type1, default: 'default-type1'
27
+ optional :type2, default: 'default-type2'
28
+ end
32
29
 
33
- get '/message' do
34
- { id: params[:id], type1: params[:type1], type2: params[:type2] }
35
- end
30
+ get '/message' do
31
+ { id: params[:id], type1: params[:type1], type2: params[:type2] }
32
+ end
36
33
 
37
- params do
38
- optional :random, default: -> { Random.rand }
39
- optional :not_random, default: Random.rand
40
- end
41
- get '/numbers' do
42
- { random_number: params[:random], non_random_number: params[:non_random_number] }
43
- end
34
+ params do
35
+ optional :random, default: -> { Random.rand }
36
+ optional :not_random, default: Random.rand
37
+ end
38
+ get '/numbers' do
39
+ { random_number: params[:random], non_random_number: params[:non_random_number] }
40
+ end
44
41
 
45
- params do
46
- optional :array, type: Array do
47
- requires :name
48
- optional :with_default, default: 'default'
49
- end
50
- end
51
- get '/array' do
52
- { array: params[:array] }
42
+ params do
43
+ optional :array, type: Array do
44
+ requires :name
45
+ optional :with_default, default: 'default'
53
46
  end
47
+ end
48
+ get '/array' do
49
+ { array: params[:array] }
50
+ end
54
51
 
55
- params do
56
- requires :thing1
57
- optional :more_things, type: Array do
58
- requires :nested_thing
59
- requires :other_thing, default: 1
60
- end
61
- end
62
- get '/optional_array' do
63
- { thing1: params[:thing1] }
52
+ params do
53
+ requires :thing1
54
+ optional :more_things, type: Array do
55
+ requires :nested_thing
56
+ requires :other_thing, default: 1
64
57
  end
58
+ end
59
+ get '/optional_array' do
60
+ { thing1: params[:thing1] }
61
+ end
65
62
 
66
- params do
67
- requires :root, type: Hash do
68
- optional :some_things, type: Array do
69
- requires :foo
70
- optional :options, type: Array do
71
- requires :name, type: String
72
- requires :value, type: String
73
- end
63
+ params do
64
+ requires :root, type: Hash do
65
+ optional :some_things, type: Array do
66
+ requires :foo
67
+ optional :options, type: Array do
68
+ requires :name, type: String
69
+ requires :value, type: String
74
70
  end
75
71
  end
76
72
  end
77
- get '/nested_optional_array' do
78
- { root: params[:root] }
79
- end
73
+ end
74
+ get '/nested_optional_array' do
75
+ { root: params[:root] }
76
+ end
80
77
 
81
- params do
82
- requires :root, type: Hash do
83
- optional :some_things, type: Array do
84
- requires :foo
85
- optional :options, type: Array do
86
- optional :name, type: String
87
- optional :value, type: String
88
- end
78
+ params do
79
+ requires :root, type: Hash do
80
+ optional :some_things, type: Array do
81
+ requires :foo
82
+ optional :options, type: Array do
83
+ optional :name, type: String
84
+ optional :value, type: String
89
85
  end
90
86
  end
91
87
  end
92
- get '/another_nested_optional_array' do
93
- { root: params[:root] }
94
- end
88
+ end
89
+ get '/another_nested_optional_array' do
90
+ { root: params[:root] }
95
91
  end
96
92
  end
97
93
  end
98
94
 
99
- def app
100
- ValidationsSpec::DefaultValidatorSpec::API
101
- end
102
-
103
95
  it 'lets you leave required values nested inside an optional blank' do
104
96
  get '/optional_array', thing1: 'stuff'
105
97
  expect(last_response.status).to eq(200)