From d17d47fbf260b539cc5537f4d2afa9ab0de12c97 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo <96243774+arielr-lt@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:33:32 -0300 Subject: [PATCH 1/3] Implement not-found error handling in API base class Added error handling for ActiveRecord not-found errors. --- app/api/base.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/api/base.rb b/app/api/base.rb index f2b45f05..eb87ad7f 100644 --- a/app/api/base.rb +++ b/app/api/base.rb @@ -3,7 +3,12 @@ module API # Main base class that defines all API versions - class Base < Grape::API +class Base < Grape::API + # Normalize ActiveRecord not-found errors to a stable API message + rescue_from ActiveRecord::RecordNotFound do |e| + model = e.respond_to?(:model) && e.model ? e.model : 'Resource' + error!({ errors: ["#{model} not found"] }, 404) + end insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger, { logger: MR.logger, filter: Class.new do From 0ba254117bbd6b4b7084f921297f4e7f849ca021 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo <96243774+arielr-lt@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:34:43 -0300 Subject: [PATCH 2/3] Simplify error message for organization not found --- spec/api/v1/publish_spec.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spec/api/v1/publish_spec.rb b/spec/api/v1/publish_spec.rb index 6d0e7472..11b317e9 100644 --- a/spec/api/v1/publish_spec.rb +++ b/spec/api/v1/publish_spec.rb @@ -706,10 +706,7 @@ it 'returns 404' do transfer_ownership expect_status(:not_found) - expect_json( - 'errors.0', - "Couldn't find Organization with 'id'=#{new_organization_id}" - ) + expect_json('errors.0', 'Organization not found') end end From cd82df010aae623bd98ca7eb349562ce99b32ac6 Mon Sep 17 00:00:00 2001 From: Alex Nizamov Date: Sat, 10 Jan 2026 04:19:34 +0500 Subject: [PATCH 3/3] Fix remaining tests and linting errors --- app/api/base.rb | 7 +------ app/api/defaults.rb | 4 +++- app/api/v1/resources.rb | 2 +- spec/api/v1/base_spec.rb | 2 +- spec/api/v1/publish_spec.rb | 5 +---- spec/api/v1/resources_spec.rb | 2 +- 6 files changed, 8 insertions(+), 14 deletions(-) diff --git a/app/api/base.rb b/app/api/base.rb index eb87ad7f..f2b45f05 100644 --- a/app/api/base.rb +++ b/app/api/base.rb @@ -3,12 +3,7 @@ module API # Main base class that defines all API versions -class Base < Grape::API - # Normalize ActiveRecord not-found errors to a stable API message - rescue_from ActiveRecord::RecordNotFound do |e| - model = e.respond_to?(:model) && e.model ? e.model : 'Resource' - error!({ errors: ["#{model} not found"] }, 404) - end + class Base < Grape::API insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger, { logger: MR.logger, filter: Class.new do diff --git a/app/api/defaults.rb b/app/api/defaults.rb index 7772e6c4..730841f1 100644 --- a/app/api/defaults.rb +++ b/app/api/defaults.rb @@ -15,7 +15,9 @@ module Defaults # Global handler for simple not found case rescue_from ActiveRecord::RecordNotFound do |e| log_backtrace(e) - error!({ errors: Array(e.message) }, 404) + + model = e.respond_to?(:model) && e.model ? e.model : 'Record' + error!({ errors: ["#{model} not found"] }, 404) end # Global handler for validation errors diff --git a/app/api/v1/resources.rb b/app/api/v1/resources.rb index 7c23dff8..364a4033 100644 --- a/app/api/v1/resources.rb +++ b/app/api/v1/resources.rb @@ -88,7 +88,7 @@ class Resources < MountableAPI @envelope.inner_resource_from_graph(params[:id]) )) rescue ActiveRecord::RecordNotFound - raise ActiveRecord::RecordNotFound, "Couldn't find Resource" + raise ActiveRecord::RecordNotFound.new(nil, 'Resource') end end end diff --git a/spec/api/v1/base_spec.rb b/spec/api/v1/base_spec.rb index c0773b04..8d736047 100644 --- a/spec/api/v1/base_spec.rb +++ b/spec/api/v1/base_spec.rb @@ -15,7 +15,7 @@ let(:test_response) { raise ActiveRecord::RecordNotFound } it { expect_status(404) } - it { expect_json('errors.0', 'ActiveRecord::RecordNotFound') } + it { expect_json('errors.0', 'Record not found') } end context 'Grape::Exceptions::Validation' do # rubocop:todo RSpec/ContextWording diff --git a/spec/api/v1/publish_spec.rb b/spec/api/v1/publish_spec.rb index 11b317e9..8d226920 100644 --- a/spec/api/v1/publish_spec.rb +++ b/spec/api/v1/publish_spec.rb @@ -817,10 +817,7 @@ it 'returns 404' do transfer_ownership expect_status(:not_found) - expect_json( - 'errors.0', - "Couldn't find Organization with 'id'=#{new_organization_id}" - ) + expect_json('errors.0', 'Organization not found') end end diff --git a/spec/api/v1/resources_spec.rb b/spec/api/v1/resources_spec.rb index 49886df0..99b09530 100644 --- a/spec/api/v1/resources_spec.rb +++ b/spec/api/v1/resources_spec.rb @@ -48,7 +48,7 @@ it 'cannot retrieve the desired resource' do expect_status(:not_found) - expect_json(errors: ["Couldn't find Resource"]) + expect_json(errors: ['Resource not found']) end end # rubocop:enable RSpec/MultipleMemoizedHelpers