Skip to content

Commit 7d1640e

Browse files
committed
Merge pull request #1242 from glennpratt/request-in-validations
Pass request to validators along with params.
2 parents eae2d14 + b15c410 commit 7d1640e

5 files changed

Lines changed: 81 additions & 30 deletions

File tree

.rubocop_todo.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2016-01-15 12:33:35 +0900 using RuboCop version 0.35.1.
3+
# on 2016-01-08 12:24:37 -0600 using RuboCop version 0.35.1.
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
@@ -22,13 +22,13 @@ Metrics/BlockNesting:
2222
# Offense count: 5
2323
# Configuration parameters: CountComments.
2424
Metrics/ClassLength:
25-
Max: 277
25+
Max: 281
2626

27-
# Offense count: 22
27+
# Offense count: 23
2828
Metrics/CyclomaticComplexity:
2929
Max: 14
3030

31-
# Offense count: 760
31+
# Offense count: 759
3232
# Configuration parameters: AllowURI, URISchemes.
3333
Metrics/LineLength:
3434
Max: 215
@@ -43,7 +43,7 @@ Metrics/MethodLength:
4343
Metrics/ModuleLength:
4444
Max: 272
4545

46-
# Offense count: 15
46+
# Offense count: 16
4747
Metrics/PerceivedComplexity:
4848
Max: 16
4949

@@ -57,7 +57,7 @@ Style/BlockDelimiters:
5757
- 'spec/grape/middleware/versioner/header_spec.rb'
5858
- 'spec/grape/request_spec.rb'
5959

60-
# Offense count: 106
60+
# Offense count: 105
6161
# Configuration parameters: Exclude.
6262
Style/Documentation:
6363
Enabled: false

lib/grape/endpoint.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def run
248248

249249
route_setting(:saved_validations).each do |validator|
250250
begin
251-
validator.validate!(params)
251+
validator.validate(@request)
252252
rescue Grape::Exceptions::Validation => e
253253
validation_errors << e
254254
end

lib/grape/validations/validators/base.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ def initialize(attrs, options, required, scope)
1717
@scope = scope
1818
end
1919

20+
# Validates a given request.
21+
# @note This method must be thread-safe.
22+
# @note Override #validate! unless you need to access the entire request.
23+
# @param request [Grape::Request] the request currently being handled
24+
# @raise [Grape::Exceptions::Validation] if validation failed
25+
# @return [void]
26+
def validate(request)
27+
validate!(request.params)
28+
end
29+
30+
# Validates a given parameter hash.
31+
# @note This method must be thread-safe.
32+
# @note Override #validate iff you need to access the entire request.
33+
# @param params [Hash] parameters to validate
34+
# @raise [Grape::Exceptions::Validation] if validation failed
35+
# @return [void]
2036
def validate!(params)
2137
attributes = AttributesIterator.new(self, @scope, params)
2238
attributes.each do |resource_params, attr_name|

lib/grape/validations/validators/coerce.rb

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ class API
55

66
module Validations
77
class CoerceValidator < Base
8+
def initialize(*_args)
9+
super
10+
@converter = Types.build_coercer(type, @option[:method])
11+
end
12+
813
def validate_param!(attr_name, params)
914
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :coerce unless params.is_a? Hash
1015
new_value = coerce_value(params[attr_name])
@@ -17,6 +22,14 @@ def validate_param!(attr_name, params)
1722

1823
private
1924

25+
# @!attribute [r] converter
26+
# Object that will be used for parameter coercion and type checking.
27+
#
28+
# See {Types.build_coercer}
29+
#
30+
# @return [Virtus::Attribute]
31+
attr_reader :converter
32+
2033
def valid_type?(val)
2134
# Special value to denote coercion failure
2235
return false if val.instance_of?(Types::InvalidValue)
@@ -49,17 +62,6 @@ def coerce_value(val)
4962
def type
5063
@option[:type]
5164
end
52-
53-
# Create and cache the attribute object
54-
# that will be used for parameter coercion
55-
# and type checking.
56-
#
57-
# See {Types.build_coercer}
58-
#
59-
# @return [Virtus::Attribute]
60-
def converter
61-
@converter ||= Types.build_coercer(type, @option[:method])
62-
end
6365
end
6466
end
6567
end

spec/grape/api/custom_validations_spec.rb

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,30 @@ def validate_param!(attr_name, params)
1010
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long"
1111
end
1212
end
13+
class InBody < Grape::Validations::PresenceValidator
14+
def validate(request)
15+
validate!(request.env['api.request.body'])
16+
end
17+
end
1318
end
1419
end
1520

16-
subject do
17-
Class.new(Grape::API) do
18-
params do
19-
requires :text, default_length: 140
20-
end
21-
get do
22-
'bacon'
21+
context 'using a custom length validator' do
22+
subject do
23+
Class.new(Grape::API) do
24+
params do
25+
requires :text, default_length: 140
26+
end
27+
get do
28+
'bacon'
29+
end
2330
end
2431
end
25-
end
2632

27-
def app
28-
subject
29-
end
33+
def app
34+
subject
35+
end
3036

31-
context 'using a custom length validator' do
3237
it 'under 140 characters' do
3338
get '/', text: 'abc'
3439
expect(last_response.status).to eq 200
@@ -45,4 +50,32 @@ def app
4550
expect(last_response.body).to eq 'bacon'
4651
end
4752
end
53+
54+
context 'using a custom body-only validator' do
55+
subject do
56+
Class.new(Grape::API) do
57+
params do
58+
requires :text, in_body: true
59+
end
60+
get do
61+
'bacon'
62+
end
63+
end
64+
end
65+
66+
def app
67+
subject
68+
end
69+
70+
it 'allows field in body' do
71+
get '/', text: 'abc'
72+
expect(last_response.status).to eq 200
73+
expect(last_response.body).to eq 'bacon'
74+
end
75+
it 'ignores field in query' do
76+
get '/', nil, text: 'abc'
77+
expect(last_response.status).to eq 400
78+
expect(last_response.body).to eq 'text is missing'
79+
end
80+
end
4881
end

0 commit comments

Comments
 (0)