Skip to content

Commit bb7bdb4

Browse files
authored
Parameter validation: Raises error for all missing (#886)
* Parameter validation: Raises error for all missing - Instead of just raising `ParamMissing` for the first missing, instead raise a compound `ParamMultipleMissing` if there are more than one missing. - Adds specs for both POST and GET requests. - Fixes #802 * Run `rubocop --auto-gen-config --exclude-limit 180` * Make BlockLength 26 in `.rubocop.yml` as well
1 parent 8c20f2b commit bb7bdb4

File tree

8 files changed

+78
-23
lines changed

8 files changed

+78
-23
lines changed

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Metrics/ClassLength:
4646
- spec/dummy/app/controllers/users_controller.rb
4747

4848
Metrics/BlockLength:
49-
Max: 25 # default
49+
Max: 26 # default
5050
Exclude:
5151
- app/controllers/apipie/apipies_controller.rb
5252
- lib/apipie/generator/swagger/param_description/composite.rb

.rubocop_todo.yml

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config --exclude-limit 180`
3-
# on 2023-06-02 23:32:14 UTC using RuboCop version 1.52.0.
3+
# on 2023-06-09 05:29:05 UTC using RuboCop version 1.52.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -118,7 +118,7 @@ Layout/ElseAlignment:
118118
- 'lib/apipie/param_description.rb'
119119
- 'lib/apipie/resource_description.rb'
120120

121-
# Offense count: 59
121+
# Offense count: 58
122122
# This cop supports safe autocorrection (--autocorrect).
123123
Layout/EmptyLineAfterGuardClause:
124124
Exclude:
@@ -783,6 +783,12 @@ Lint/Void:
783783
Metrics/AbcSize:
784784
Max: 96
785785

786+
# Offense count: 1
787+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
788+
# AllowedMethods: refine
789+
Metrics/BlockLength:
790+
Max: 26
791+
786792
# Offense count: 4
787793
# Configuration parameters: CountBlocks.
788794
Metrics/BlockNesting:
@@ -793,11 +799,16 @@ Metrics/BlockNesting:
793799
Metrics/CyclomaticComplexity:
794800
Max: 24
795801

796-
# Offense count: 78
802+
# Offense count: 79
797803
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
798804
Metrics/MethodLength:
799805
Max: 58
800806

807+
# Offense count: 1
808+
# Configuration parameters: CountComments, CountAsOne.
809+
Metrics/ModuleLength:
810+
Max: 101
811+
801812
# Offense count: 4
802813
# Configuration parameters: CountKeywordArgs.
803814
Metrics/ParameterLists:
@@ -1048,7 +1059,7 @@ RSpec/EmptyLineAfterHook:
10481059
RSpec/ExampleLength:
10491060
Max: 85
10501061

1051-
# Offense count: 158
1062+
# Offense count: 159
10521063
# This cop supports safe autocorrection (--autocorrect).
10531064
# Configuration parameters: CustomTransform, IgnoredWords, DisallowedExamples.
10541065
# DisallowedExamples: works
@@ -1137,7 +1148,7 @@ RSpec/MessageSpies:
11371148
RSpec/MultipleExpectations:
11381149
Max: 19
11391150

1140-
# Offense count: 154
1151+
# Offense count: 156
11411152
# Configuration parameters: AllowSubject.
11421153
RSpec/MultipleMemoizedHelpers:
11431154
Max: 15
@@ -1162,18 +1173,17 @@ RSpec/NamedSubject:
11621173
- 'spec/lib/swagger/rake_swagger_spec.rb'
11631174
- 'spec/lib/swagger/swagger_dsl_spec.rb'
11641175

1165-
# Offense count: 93
1176+
# Offense count: 94
11661177
# Configuration parameters: AllowedGroups.
11671178
RSpec/NestedGroups:
11681179
Max: 6
11691180

1170-
# Offense count: 2
1181+
# Offense count: 1
11711182
# Configuration parameters: AllowedPatterns.
11721183
# AllowedPatterns: ^expect_, ^assert_
11731184
RSpec/NoExpectationExample:
11741185
Exclude:
11751186
- 'spec/controllers/users_controller_spec.rb'
1176-
- 'spec/test_engine/memes_controller_spec.rb'
11771187

11781188
# Offense count: 2
11791189
# This cop supports safe autocorrection (--autocorrect).
@@ -1366,7 +1376,7 @@ Style/AndOr:
13661376
Exclude:
13671377
- 'lib/apipie/param_description.rb'
13681378

1369-
# Offense count: 17
1379+
# Offense count: 18
13701380
# This cop supports safe autocorrection (--autocorrect).
13711381
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
13721382
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
@@ -1522,7 +1532,7 @@ Style/EmptyElse:
15221532
- 'lib/apipie/extractor/recorder.rb'
15231533
- 'lib/apipie/extractor/writer.rb'
15241534

1525-
# Offense count: 26
1535+
# Offense count: 27
15261536
# This cop supports safe autocorrection (--autocorrect).
15271537
# Configuration parameters: EnforcedStyle.
15281538
# SupportedStyles: compact, expanded
@@ -1765,7 +1775,6 @@ Style/Proc:
17651775
Style/RaiseArgs:
17661776
Exclude:
17671777
- 'lib/apipie/application.rb'
1768-
- 'lib/apipie/dsl_definition.rb'
17691778
- 'lib/apipie/extractor/writer.rb'
17701779
- 'lib/apipie/param_description.rb'
17711780
- 'lib/apipie/see_description.rb'
@@ -1917,7 +1926,7 @@ Style/StringConcatenation:
19171926
- 'lib/apipie/application.rb'
19181927
- 'lib/apipie/extractor/writer.rb'
19191928

1920-
# Offense count: 1210
1929+
# Offense count: 1212
19211930
# This cop supports safe autocorrection (--autocorrect).
19221931
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
19231932
# SupportedStyles: single_quotes, double_quotes

lib/apipie/dsl_definition.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,11 @@ def _apipie_define_validators(description)
241241
method_params = self.class._apipie_get_method_params(action_name)
242242

243243
if Apipie.configuration.validate_presence?
244-
method_params.each do |_, param|
245-
# check if required parameters are present
246-
raise ParamMissing.new(param) if param.required && !params.key?(param.name)
244+
Validator::BaseValidator.raise_if_missing_params do |missing|
245+
method_params.each do |_, param|
246+
# check if required parameters are present
247+
missing << param if param.required && !params.key?(param.name)
248+
end
247249
end
248250
end
249251

@@ -285,7 +287,6 @@ def _apipie_define_validators(description)
285287
old_method.bind(self).call(*args)
286288
end
287289
end
288-
289290
end
290291
end
291292

lib/apipie/errors.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ def initialize(param)
2424
end
2525
end
2626

27+
class ParamMultipleMissing < ParamError
28+
attr_accessor :params
29+
30+
def initialize(params)
31+
@params = params
32+
end
33+
34+
def to_s
35+
params.map do |param|
36+
ParamMissing.new(param).to_s
37+
end.join("\n")
38+
end
39+
end
40+
2741
class ParamMissing < DefinedParamError
2842
def to_s
2943
unless @param.options[:missing_message].nil?

lib/apipie/validator.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ def self.find(param_description, argument, options, block)
3838
return nil
3939
end
4040

41+
def self.raise_if_missing_params
42+
missing_params = []
43+
yield missing_params
44+
if missing_params.size > 1
45+
raise ParamMultipleMissing.new(missing_params)
46+
elsif missing_params.size == 1
47+
raise ParamMissing.new(missing_params.first)
48+
end
49+
end
50+
4151
# check if value is valid
4252
def valid?(value)
4353
if self.validate(value)
@@ -345,14 +355,18 @@ def params_ordered
345355

346356
def validate(value)
347357
return false if !value.is_a? Hash
348-
@hash_params&.each do |k, p|
349-
if Apipie.configuration.validate_presence?
350-
raise ParamMissing.new(p) if p.required && !value.key?(k)
351-
end
352-
if Apipie.configuration.validate_value?
353-
p.validate(value[k]) if value.key?(k)
358+
359+
BaseValidator.raise_if_missing_params do |missing|
360+
@hash_params&.each do |k, p|
361+
if Apipie.configuration.validate_presence?
362+
missing << p if p.required && !value.key?(k)
363+
end
364+
if Apipie.configuration.validate_value?
365+
p.validate(value[k]) if value.key?(k)
366+
end
354367
end
355368
end
369+
356370
return true
357371
end
358372

spec/controllers/users_controller_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def compare_hashes(h1, h2)
3737
expect(methods.keys).to include(:update)
3838
expect(methods.keys).to include(:two_urls)
3939
expect(methods.keys).to include(:action_with_headers)
40+
expect(methods.keys).to include(:multiple_required_params)
4041
end
4142

4243
it "should contain info about resource" do
@@ -101,6 +102,10 @@ def reload_controllers
101102
expect { get :show, :params => { :id => 5 }}.to raise_error(Apipie::ParamMissing, /session_parameter_is_required/)
102103
end
103104

105+
it "should fail if multiple required parameters are missing" do
106+
expect { get :multiple_required_params }.to raise_error(Apipie::ParamMultipleMissing, /required_param1.*\n.*required_param2|required_param2.*\n.*required_parameter1/)
107+
end
108+
104109
it "should pass if required parameter has wrong type" do
105110
expect { get :show, :params => { :id => 5 , :session => "secret_hash" }}.not_to raise_error
106111
expect { get :show, :params => { :id => "ten" , :session => "secret_hash" }}.not_to raise_error
@@ -246,6 +251,11 @@ def reload_controllers
246251
post :create, :params => { :user => { :name => "root", :pass => "12345", :membership => "____" } }
247252
}.to raise_error(Apipie::ParamInvalid, /membership/)
248253

254+
# Should include both pass and name
255+
expect {
256+
post :create, :params => { :user => { :membership => "standard" } }
257+
}.to raise_error(Apipie::ParamMultipleMissing, /pass.*\n.*name|name.*\n.*pass/)
258+
249259
expect {
250260
post :create, :params => { :user => { :name => "root" } }
251261
}.to raise_error(Apipie::ParamMissing, /pass/)

spec/dummy/app/controllers/users_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,10 @@ def create_route
301301
header :HeaderNameWithDefaultValue, 'Header with default value', required: true, default: 'default value'
302302
def action_with_headers
303303
end
304+
305+
api :GET, '/users/multiple_required_params'
306+
param :required_param1, String, required: true
307+
param :required_param2, String, required: true
308+
def multiple_required_params
309+
end
304310
end

spec/dummy/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
resources :users do
99
collection do
1010
post :create_route
11+
get :multiple_required_params
1112
end
1213
end
1314
resources :concerns, :only => [:index, :show]

0 commit comments

Comments
 (0)