grape 1.5.2 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +33 -3
  5. data/UPGRADING.md +71 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +13 -17
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/desc.rb +3 -5
  11. data/lib/grape/dsl/headers.rb +5 -2
  12. data/lib/grape/dsl/helpers.rb +7 -5
  13. data/lib/grape/dsl/inside_route.rb +17 -8
  14. data/lib/grape/dsl/middleware.rb +4 -4
  15. data/lib/grape/dsl/parameters.rb +3 -3
  16. data/lib/grape/dsl/request_response.rb +9 -6
  17. data/lib/grape/dsl/routing.rb +2 -2
  18. data/lib/grape/dsl/settings.rb +5 -5
  19. data/lib/grape/endpoint.rb +21 -36
  20. data/lib/grape/error_formatter/json.rb +2 -6
  21. data/lib/grape/error_formatter/xml.rb +2 -6
  22. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  23. data/lib/grape/exceptions/validation.rb +1 -2
  24. data/lib/grape/formatter/json.rb +1 -0
  25. data/lib/grape/formatter/serializable_hash.rb +2 -1
  26. data/lib/grape/formatter/xml.rb +1 -0
  27. data/lib/grape/locale/en.yml +1 -1
  28. data/lib/grape/middleware/auth/dsl.rb +7 -1
  29. data/lib/grape/middleware/base.rb +3 -1
  30. data/lib/grape/middleware/formatter.rb +4 -4
  31. data/lib/grape/middleware/stack.rb +2 -2
  32. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  33. data/lib/grape/middleware/versioner/header.rb +6 -4
  34. data/lib/grape/middleware/versioner/param.rb +1 -0
  35. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  36. data/lib/grape/middleware/versioner/path.rb +2 -0
  37. data/lib/grape/parser/json.rb +1 -1
  38. data/lib/grape/parser/xml.rb +1 -1
  39. data/lib/grape/path.rb +1 -0
  40. data/lib/grape/request.rb +3 -0
  41. data/lib/grape/router/pattern.rb +1 -1
  42. data/lib/grape/router/route.rb +2 -2
  43. data/lib/grape/router.rb +6 -0
  44. data/lib/grape/util/inheritable_setting.rb +1 -3
  45. data/lib/grape/util/lazy_value.rb +3 -2
  46. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  47. data/lib/grape/validations/params_scope.rb +88 -55
  48. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  49. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  50. data/lib/grape/validations/types/json.rb +2 -1
  51. data/lib/grape/validations/types/primitive_coercer.rb +3 -3
  52. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  53. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  54. data/lib/grape/validations/validators/as.rb +6 -8
  55. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  56. data/lib/grape/validations/validators/base.rb +75 -70
  57. data/lib/grape/validations/validators/coerce.rb +63 -79
  58. data/lib/grape/validations/validators/default.rb +37 -34
  59. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  60. data/lib/grape/validations/validators/except_values.rb +13 -11
  61. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  62. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  63. data/lib/grape/validations/validators/presence.rb +7 -4
  64. data/lib/grape/validations/validators/regexp.rb +8 -5
  65. data/lib/grape/validations/validators/same_as.rb +18 -15
  66. data/lib/grape/validations/validators/values.rb +61 -56
  67. data/lib/grape/validations.rb +6 -0
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +4 -1
  70. data/spec/grape/api/custom_validations_spec.rb +77 -45
  71. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  72. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  73. data/spec/grape/api/invalid_format_spec.rb +2 -0
  74. data/spec/grape/api/recognize_path_spec.rb +1 -1
  75. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  76. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  77. data/spec/grape/api_remount_spec.rb +16 -15
  78. data/spec/grape/api_spec.rb +510 -220
  79. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  80. data/spec/grape/dsl/headers_spec.rb +39 -9
  81. data/spec/grape/dsl/helpers_spec.rb +3 -2
  82. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  83. data/spec/grape/dsl/logger_spec.rb +16 -18
  84. data/spec/grape/dsl/middleware_spec.rb +2 -1
  85. data/spec/grape/dsl/parameters_spec.rb +2 -0
  86. data/spec/grape/dsl/request_response_spec.rb +1 -0
  87. data/spec/grape/dsl/routing_spec.rb +10 -7
  88. data/spec/grape/endpoint/declared_spec.rb +259 -12
  89. data/spec/grape/endpoint_spec.rb +77 -55
  90. data/spec/grape/entity_spec.rb +22 -22
  91. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  92. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  93. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  94. data/spec/grape/exceptions/validation_spec.rb +5 -3
  95. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  96. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  97. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  98. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  99. data/spec/grape/loading_spec.rb +8 -8
  100. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  101. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  102. data/spec/grape/middleware/base_spec.rb +24 -15
  103. data/spec/grape/middleware/error_spec.rb +2 -2
  104. data/spec/grape/middleware/exception_spec.rb +111 -161
  105. data/spec/grape/middleware/formatter_spec.rb +27 -6
  106. data/spec/grape/middleware/globals_spec.rb +7 -4
  107. data/spec/grape/middleware/stack_spec.rb +14 -12
  108. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  109. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  110. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  111. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  112. data/spec/grape/middleware/versioner_spec.rb +1 -1
  113. data/spec/grape/parser_spec.rb +4 -0
  114. data/spec/grape/path_spec.rb +52 -52
  115. data/spec/grape/presenters/presenter_spec.rb +7 -6
  116. data/spec/grape/request_spec.rb +6 -4
  117. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  118. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  119. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  120. data/spec/grape/util/stackable_values_spec.rb +7 -5
  121. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  122. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  123. data/spec/grape/validations/params_scope_spec.rb +46 -10
  124. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
  125. data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
  126. data/spec/grape/validations/types_spec.rb +8 -8
  127. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  128. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  129. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  130. data/spec/grape/validations/validators/coerce_spec.rb +99 -22
  131. data/spec/grape/validations/validators/default_spec.rb +72 -78
  132. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  133. data/spec/grape/validations/validators/except_values_spec.rb +3 -3
  134. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  135. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  136. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  137. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  138. data/spec/grape/validations/validators/values_spec.rb +183 -178
  139. data/spec/grape/validations_spec.rb +99 -58
  140. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  141. data/spec/integration/multi_json/json_spec.rb +1 -1
  142. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  143. data/spec/shared/versioning_examples.rb +12 -9
  144. data/spec/spec_helper.rb +12 -2
  145. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  146. metadata +102 -101
@@ -2,73 +2,67 @@
2
2
 
3
3
  require 'spec_helper'
4
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
5
+ describe Grape::Validations::Validators::AtLeastOneOfValidator do
6
+ let_it_be(:app) do
7
+ Class.new(Grape::API) do
8
+ rescue_from Grape::Exceptions::ValidationErrors do |e|
9
+ error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
10
+ end
15
11
 
16
- params do
17
- optional :beer, :wine, :grapefruit
18
- at_least_one_of :beer, :wine, :grapefruit
19
- end
20
- post do
21
- end
12
+ params do
13
+ optional :beer, :wine, :grapefruit
14
+ at_least_one_of :beer, :wine, :grapefruit
15
+ end
16
+ post do
17
+ end
22
18
 
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
19
+ params do
20
+ optional :beer, :wine, :grapefruit, :other
21
+ at_least_one_of :beer, :wine, :grapefruit
22
+ end
23
+ post 'mixed-params' do
24
+ end
29
25
 
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
26
+ params do
27
+ optional :beer, :wine, :grapefruit
28
+ at_least_one_of :beer, :wine, :grapefruit, message: 'you should choose something'
29
+ end
30
+ post '/custom-message' do
31
+ end
36
32
 
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
33
+ params do
34
+ requires :item, type: Hash do
35
+ optional :beer, :wine, :grapefruit
36
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
37
+ end
38
+ end
39
+ post '/nested-hash' do
40
+ end
45
41
 
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
42
+ params do
43
+ requires :items, type: Array do
44
+ optional :beer, :wine, :grapefruit
45
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
46
+ end
47
+ end
48
+ post '/nested-array' do
49
+ end
54
50
 
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
51
+ params do
52
+ requires :items, type: Array do
53
+ requires :nested_items, type: Array do
54
+ optional :beer, :wine, :grapefruit
55
+ at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
64
56
  end
65
57
  end
66
58
  end
59
+ post '/deeply-nested-array' do
60
+ end
67
61
  end
62
+ end
68
63
 
69
- def app
70
- ValidationsSpec::AtLeastOneOfValidatorSpec::API
71
- end
64
+ describe '#validate!' do
65
+ subject(:validate) { post path, params }
72
66
 
73
67
  context 'when all restricted params are present' do
74
68
  let(:path) { '/' }
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Grape::Validations::CoerceValidator do
5
+ describe Grape::Validations::Validators::CoerceValidator do
6
6
  subject do
7
7
  Class.new(Grape::API)
8
8
  end
@@ -23,7 +23,7 @@ describe Grape::Validations::CoerceValidator do
23
23
  end
24
24
 
25
25
  context 'i18n' do
26
- after :each do
26
+ after do
27
27
  I18n.available_locales = %i[en]
28
28
  I18n.locale = :en
29
29
  I18n.default_locale = :en
@@ -31,9 +31,9 @@ describe Grape::Validations::CoerceValidator do
31
31
 
32
32
  it 'i18n error on malformed input' do
33
33
  I18n.available_locales = %i[en zh-CN]
34
- I18n.load_path << File.expand_path('../zh-CN.yml', __FILE__)
34
+ I18n.load_path << File.expand_path('zh-CN.yml', __dir__)
35
35
  I18n.reload!
36
- I18n.locale = 'zh-CN'.to_sym
36
+ I18n.locale = :'zh-CN'
37
37
  subject.params do
38
38
  requires :age, type: Integer
39
39
  end
@@ -48,7 +48,7 @@ describe Grape::Validations::CoerceValidator do
48
48
 
49
49
  it 'gives an english fallback error when default locale message is blank' do
50
50
  I18n.available_locales = %i[en pt-BR]
51
- I18n.locale = 'pt-BR'.to_sym
51
+ I18n.locale = :'pt-BR'
52
52
  subject.params do
53
53
  requires :age, type: Integer
54
54
  end
@@ -83,10 +83,11 @@ describe Grape::Validations::CoerceValidator do
83
83
  context 'on custom coercion rules' do
84
84
  before do
85
85
  subject.params do
86
- requires :a, types: { value: [Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
87
- if val == 'yup'
86
+ requires :a, types: { value: [Grape::API::Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
87
+ case val
88
+ when 'yup'
88
89
  true
89
- elsif val == 'false'
90
+ when 'false'
90
91
  0
91
92
  else
92
93
  val
@@ -170,9 +171,9 @@ describe Grape::Validations::CoerceValidator do
170
171
  expect(last_response.body).to eq('BigDecimal 45.1')
171
172
  end
172
173
 
173
- it 'Boolean' do
174
+ it 'Grape::API::Boolean' do
174
175
  subject.params do
175
- requires :boolean, type: Boolean
176
+ requires :boolean, type: Grape::API::Boolean
176
177
  end
177
178
  subject.post '/boolean' do
178
179
  params[:boolean]
@@ -369,9 +370,9 @@ describe Grape::Validations::CoerceValidator do
369
370
  end
370
371
  end
371
372
 
372
- it 'Boolean' do
373
+ it 'Grape::API::Boolean' do
373
374
  subject.params do
374
- requires :boolean, type: Boolean
375
+ requires :boolean, type: Grape::API::Boolean
375
376
  end
376
377
  subject.get '/boolean' do
377
378
  params[:boolean].class
@@ -650,7 +651,7 @@ describe Grape::Validations::CoerceValidator do
650
651
 
651
652
  it 'parses parameters with Array[Array[String]] type and coerce_with' do
652
653
  subject.params do
653
- requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(/,/).map(&:strip)] : val }
654
+ requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(',').map(&:strip)] : val }
654
655
  end
655
656
  subject.post '/coerce_nested_strings' do
656
657
  params[:values]
@@ -706,6 +707,44 @@ describe Grape::Validations::CoerceValidator do
706
707
  expect(JSON.parse(last_response.body)).to eq([1, 1, 1, 1])
707
708
  end
708
709
 
710
+ context 'Array type and coerce_with should' do
711
+ before do
712
+ subject.params do
713
+ optional :arr, type: Array, coerce_with: (lambda do |val|
714
+ if val.nil?
715
+ []
716
+ else
717
+ val
718
+ end
719
+ end)
720
+ end
721
+ subject.get '/' do
722
+ params[:arr].class.to_s
723
+ end
724
+ end
725
+
726
+ it 'coerce nil value to array' do
727
+ get '/', arr: nil
728
+
729
+ expect(last_response.status).to eq(200)
730
+ expect(last_response.body).to eq('Array')
731
+ end
732
+
733
+ it 'not coerce missing field' do
734
+ get '/'
735
+
736
+ expect(last_response.status).to eq(200)
737
+ expect(last_response.body).to eq('NilClass')
738
+ end
739
+
740
+ it 'coerce array as array' do
741
+ get '/', arr: []
742
+
743
+ expect(last_response.status).to eq(200)
744
+ expect(last_response.body).to eq('Array')
745
+ end
746
+ end
747
+
709
748
  it 'uses parse where available' do
710
749
  subject.params do
711
750
  requires :ints, type: Array, coerce_with: JSON do
@@ -754,13 +793,52 @@ describe Grape::Validations::CoerceValidator do
754
793
  expect(last_response.body).to eq('3')
755
794
  end
756
795
 
796
+ context 'Integer type and coerce_with should' do
797
+ before do
798
+ subject.params do
799
+ optional :int, type: Integer, coerce_with: (lambda do |val|
800
+ if val.nil?
801
+ 0
802
+ else
803
+ val.to_i
804
+ end
805
+ end)
806
+ end
807
+ subject.get '/' do
808
+ params[:int].class.to_s
809
+ end
810
+ end
811
+
812
+ it 'coerce nil value to integer' do
813
+ get '/', int: nil
814
+
815
+ expect(last_response.status).to eq(200)
816
+ expect(last_response.body).to eq('Integer')
817
+ end
818
+
819
+ it 'not coerce missing field' do
820
+ get '/'
821
+
822
+ expect(last_response.status).to eq(200)
823
+ expect(last_response.body).to eq('NilClass')
824
+ end
825
+
826
+ it 'coerce integer as integer' do
827
+ get '/', int: 1
828
+
829
+ expect(last_response.status).to eq(200)
830
+ expect(last_response.body).to eq('Integer')
831
+ end
832
+ end
833
+
757
834
  context 'Integer type and coerce_with potentially returning nil' do
758
835
  before do
759
836
  subject.params do
760
837
  requires :int, type: Integer, coerce_with: (lambda do |val|
761
- if val == '0'
838
+ case val
839
+ when '0'
762
840
  nil
763
- elsif val.match?(/^-?\d+$/)
841
+ when /^-?\d+$/
764
842
  val.to_i
765
843
  else
766
844
  val
@@ -940,11 +1018,9 @@ describe Grape::Validations::CoerceValidator do
940
1018
  end
941
1019
 
942
1020
  context 'multiple types' do
943
- Boolean = Grape::API::Boolean
944
-
945
1021
  it 'coerces to first possible type' do
946
1022
  subject.params do
947
- requires :a, types: [Boolean, Integer, String]
1023
+ requires :a, types: [Grape::API::Boolean, Integer, String]
948
1024
  end
949
1025
  subject.get '/' do
950
1026
  params[:a].class.to_s
@@ -965,7 +1041,7 @@ describe Grape::Validations::CoerceValidator do
965
1041
 
966
1042
  it 'fails when no coercion is possible' do
967
1043
  subject.params do
968
- requires :a, types: [Boolean, Integer]
1044
+ requires :a, types: [Grape::API::Boolean, Integer]
969
1045
  end
970
1046
  subject.get '/' do
971
1047
  params[:a].class.to_s
@@ -1124,10 +1200,11 @@ describe Grape::Validations::CoerceValidator do
1124
1200
  context 'custom coercion rules' do
1125
1201
  before do
1126
1202
  subject.params do
1127
- requires :a, types: [Boolean, String], coerce_with: (lambda do |val|
1128
- if val == 'yup'
1203
+ requires :a, types: [Grape::API::Boolean, String], coerce_with: (lambda do |val|
1204
+ case val
1205
+ when 'yup'
1129
1206
  true
1130
- elsif val == 'false'
1207
+ when 'false'
1131
1208
  0
1132
1209
  else
1133
1210
  val
@@ -2,104 +2,98 @@
2
2
 
3
3
  require 'spec_helper'
4
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
5
+ describe Grape::Validations::Validators::DefaultValidator do
6
+ let_it_be(:app) do
7
+ Class.new(Grape::API) do
8
+ default_format :json
9
+
10
+ params do
11
+ optional :id
12
+ optional :type, default: 'default-type'
13
+ end
14
+ get '/' do
15
+ { id: params[:id], type: params[:type] }
16
+ end
18
17
 
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
18
+ params do
19
+ optional :type1, default: 'default-type1'
20
+ optional :type2, default: 'default-type2'
21
+ end
22
+ get '/user' do
23
+ { type1: params[:type1], type2: params[:type2] }
24
+ end
26
25
 
27
- params do
28
- requires :id
29
- optional :type1, default: 'default-type1'
30
- optional :type2, default: 'default-type2'
31
- end
26
+ params do
27
+ requires :id
28
+ optional :type1, default: 'default-type1'
29
+ optional :type2, default: 'default-type2'
30
+ end
32
31
 
33
- get '/message' do
34
- { id: params[:id], type1: params[:type1], type2: params[:type2] }
35
- end
32
+ get '/message' do
33
+ { id: params[:id], type1: params[:type1], type2: params[:type2] }
34
+ end
36
35
 
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
36
+ params do
37
+ optional :random, default: -> { Random.rand }
38
+ optional :not_random, default: Random.rand
39
+ end
40
+ get '/numbers' do
41
+ { random_number: params[:random], non_random_number: params[:non_random_number] }
42
+ end
44
43
 
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] }
44
+ params do
45
+ optional :array, type: Array do
46
+ requires :name
47
+ optional :with_default, default: 'default'
53
48
  end
49
+ end
50
+ get '/array' do
51
+ { array: params[:array] }
52
+ end
54
53
 
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] }
54
+ params do
55
+ requires :thing1
56
+ optional :more_things, type: Array do
57
+ requires :nested_thing
58
+ requires :other_thing, default: 1
64
59
  end
60
+ end
61
+ get '/optional_array' do
62
+ { thing1: params[:thing1] }
63
+ end
65
64
 
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
65
+ params do
66
+ requires :root, type: Hash do
67
+ optional :some_things, type: Array do
68
+ requires :foo
69
+ optional :options, type: Array do
70
+ requires :name, type: String
71
+ requires :value, type: String
74
72
  end
75
73
  end
76
74
  end
77
- get '/nested_optional_array' do
78
- { root: params[:root] }
79
- end
75
+ end
76
+ get '/nested_optional_array' do
77
+ { root: params[:root] }
78
+ end
80
79
 
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
80
+ params do
81
+ requires :root, type: Hash do
82
+ optional :some_things, type: Array do
83
+ requires :foo
84
+ optional :options, type: Array do
85
+ optional :name, type: String
86
+ optional :value, type: String
89
87
  end
90
88
  end
91
89
  end
92
- get '/another_nested_optional_array' do
93
- { root: params[:root] }
94
- end
90
+ end
91
+ get '/another_nested_optional_array' do
92
+ { root: params[:root] }
95
93
  end
96
94
  end
97
95
  end
98
96
 
99
- def app
100
- ValidationsSpec::DefaultValidatorSpec::API
101
- end
102
-
103
97
  it 'lets you leave required values nested inside an optional blank' do
104
98
  get '/optional_array', thing1: 'stuff'
105
99
  expect(last_response.status).to eq(200)