Skip to content

Commit bfe9704

Browse files
author
Matt Zukowski
committed
allow custom param coercion failure messages
Custom param types can now report why coercion failed in their .parse method by returning an InvalidValue initialized with an error message. For example: Grape::Validations::Types::InvalidValue.new "is too short"
1 parent a9a29a4 commit bfe9704

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

lib/grape/validations/types.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ module Validations
2424
module Types
2525
# Instances of this class may be used as tokens to denote that
2626
# a parameter value could not be coerced.
27-
class InvalidValue; end
27+
class InvalidValue
28+
attr_reader :message
29+
def initialize(message = nil)
30+
@message = message
31+
end
32+
end
2833

2934
# Types representing a single value, which are coerced through Virtus
3035
# or special logic in Grape.

lib/grape/validations/validators/coerce.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ def validate_param!(attr_name, params)
1111
if valid_type?(new_value)
1212
params[attr_name] = new_value
1313
else
14-
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :coerce
14+
bad_value = new_value
15+
if bad_value.is_a?(Types::InvalidValue) && !bad_value.message.nil?
16+
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: bad_value.message.to_s
17+
else
18+
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :coerce
19+
end
1520
end
1621
end
1722

spec/grape/validations/params_scope_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,54 @@ def initialize(value)
118118
expect(last_response.status).to eq(400)
119119
expect(last_response.body).to match(/foo is invalid/)
120120
end
121+
122+
context 'when the parse method returns an InvalidValue' do
123+
module ParamsScopeSpec
124+
class AnotherCustomType
125+
attr_reader :value
126+
def self.parse(value)
127+
case value
128+
when 'invalid with message'
129+
Grape::Validations::Types::InvalidValue.new "is not correct"
130+
when 'invalid without message'
131+
Grape::Validations::Types::InvalidValue.new
132+
else
133+
new(value)
134+
end
135+
end
136+
137+
def initialize(value)
138+
@value = value
139+
end
140+
end
141+
end
142+
143+
context 'with a message' do
144+
it 'fails with the InvalidValue\'s error message' do
145+
subject.params do
146+
requires :foo, type: ParamsScopeSpec::AnotherCustomType
147+
end
148+
subject.get('/types') { params[:foo].value }
149+
150+
get '/types', foo: 'invalid with message'
151+
expect(last_response.status).to eq(400)
152+
expect(last_response.body).to match(/foo is not correct/)
153+
end
154+
end
155+
156+
context 'without a message' do
157+
it 'fails with the default coercion failure message' do
158+
subject.params do
159+
requires :foo, type: ParamsScopeSpec::AnotherCustomType
160+
end
161+
subject.get('/types') { params[:foo].value }
162+
163+
get '/types', foo: 'invalid without message'
164+
expect(last_response.status).to eq(400)
165+
expect(last_response.body).to match(/foo is invalid/)
166+
end
167+
end
168+
end
121169
end
122170

123171
context 'array without coerce type explicitly given' do

0 commit comments

Comments
 (0)