Skip to content

Commit 2b8567a

Browse files
authored
Fix rescue_from ValidationErrors exception (#2480)
* Fix rescue_from ValidationErrors exception * Update CHANGELOG
1 parent 838c75e commit 2b8567a

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
* [#2471](https://github.com/ruby-grape/grape/pull/2471): Fix absence of original_exception and/or backtrace even if passed in error! - [@numbata](https://github.com/numbata).
1111
* [#2478](https://github.com/ruby-grape/grape/pull/2478): Fix rescue_from with invalid response - [@ericproulx](https://github.com/ericproulx).
12+
* [#2480](https://github.com/ruby-grape/grape/pull/2480): Fix rescue_from ValidationErrors exception - [@numbata](https://github.com/numbata).
1213
* Your contribution here.
1314

1415
### 2.1.3 (2024-07-13)

lib/grape/error_formatter/json.rb

+13-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ class << self
99
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
1010
result = wrap_message(present(message, env))
1111

12-
rescue_options = options[:rescue_options] || {}
13-
result = result.merge(backtrace: backtrace) if rescue_options[:backtrace] && backtrace && !backtrace.empty?
14-
result = result.merge(original_exception: original_exception.inspect) if rescue_options[:original_exception] && original_exception
12+
result = merge_rescue_options(result, backtrace, options, original_exception) if result.is_a?(Hash)
13+
1514
::Grape::Json.dump(result)
1615
end
1716

1817
private
1918

2019
def wrap_message(message)
21-
if message.is_a?(Exceptions::ValidationErrors) || message.is_a?(Hash)
20+
if message.is_a?(Hash)
2221
message
22+
elsif message.is_a?(Exceptions::ValidationErrors)
23+
message.as_json
2324
else
2425
{ error: ensure_utf8(message) }
2526
end
@@ -30,6 +31,14 @@ def ensure_utf8(message)
3031

3132
message.encode('UTF-8', invalid: :replace, undef: :replace)
3233
end
34+
35+
def merge_rescue_options(result, backtrace, options, original_exception)
36+
rescue_options = options[:rescue_options] || {}
37+
result = result.merge(backtrace: backtrace) if rescue_options[:backtrace] && backtrace && !backtrace.empty?
38+
result = result.merge(original_exception: original_exception.inspect) if rescue_options[:original_exception] && original_exception
39+
40+
result
41+
end
3342
end
3443
end
3544
end

spec/grape/api_spec.rb

+51
Original file line numberDiff line numberDiff line change
@@ -2743,6 +2743,57 @@ def self.call(message, _backtrace, _options, _env, _original_exception)
27432743
it { is_expected.to have_key('backtrace') & have_key('original-exception') }
27442744
end
27452745
end
2746+
2747+
context 'when rescue validation errors include backtrace and original exception' do
2748+
let(:app) do
2749+
response_type = response_format
2750+
2751+
Class.new(Grape::API) do
2752+
format response_type
2753+
2754+
rescue_from Grape::Exceptions::ValidationErrors, backtrace: true, original_exception: true do |e|
2755+
error!(e, 418, {}, e.backtrace, e)
2756+
end
2757+
2758+
params do
2759+
requires :weather
2760+
end
2761+
get '/forecast' do
2762+
'sunny'
2763+
end
2764+
end
2765+
end
2766+
2767+
before do
2768+
get '/forecast'
2769+
end
2770+
2771+
context 'with json response type format' do
2772+
subject { JSON.parse(last_response.body) }
2773+
2774+
let(:response_format) { :json }
2775+
2776+
it 'does not include backtrace or original exception' do
2777+
expect(subject).to match([{ 'messages' => ['is missing'], 'params' => ['weather'] }])
2778+
end
2779+
end
2780+
2781+
context 'with txt response type format' do
2782+
subject { last_response.body }
2783+
2784+
let(:response_format) { :txt }
2785+
2786+
it { is_expected.to include('backtrace', 'original exception') }
2787+
end
2788+
2789+
context 'with xml response type format' do
2790+
subject { Grape::Xml.parse(last_response.body)['error'] }
2791+
2792+
let(:response_format) { :xml }
2793+
2794+
it { is_expected.to have_key('backtrace') & have_key('original-exception') }
2795+
end
2796+
end
27462797
end
27472798

27482799
describe '.content_type' do

0 commit comments

Comments
 (0)