Skip to content

Add block support to rescue_from for custom error handling#2

Merged
sebscholl merged 4 commits intozarpay:mainfrom
obie:feature/rescue-from-block-support
Nov 20, 2025
Merged

Add block support to rescue_from for custom error handling#2
sebscholl merged 4 commits intozarpay:mainfrom
obie:feature/rescue-from-block-support

Conversation

@obie
Copy link
Copy Markdown
Contributor

@obie obie commented Nov 20, 2025

Summary

This PR adds block support to the rescue_from method, allowing services to customize error handling with full control over the response.

Motivation

Currently, rescue_from only supports a static error type via the use: parameter. This PR enables dynamic error handling by accepting a block that can:

  • Return custom failure messages
  • Return success despite catching an exception
  • Dynamically choose error types

Implementation

The implementation uses a BlockContext class that provides success() and failure() methods matching the service interface. The block is executed via instance_exec, giving a natural API:

rescue_from SomeError do |e|
  failure("Custom error: #{e.message}")
end

Key Features

  • Clean API: No extra parameters needed - just call success/failure directly
  • Full backward compatibility: Existing rescue_from declarations continue to work
  • Multiple handlers: Different blocks can handle different error types
  • Recovery from errors: Can return success despite catching an exception

Testing

Comprehensive test coverage includes:

  • Custom failure messages
  • Returning success despite exceptions
  • Dynamic error type selection
  • Multiple rescue_from blocks
  • Backward compatibility verification

All existing tests pass without modification.

Example Usage

class MyService < Servus::Base
  # Custom error message
  rescue_from ActiveRecord::RecordInvalid do |e|
    failure("Failed to save: #{e.message}")
  end
  
  # Recover from error
  rescue_from RetryableError do |e|
    Rails.logger.warn("Recovered from: #{e.message}")
    success({ recovered: true, fallback_used: true })
  end
  
  # Dynamic error type
  rescue_from ValidationError do |e|
    failure(e.message, type: Servus::Support::Errors::UnprocessableEntityError)
  end
  
  # Old syntax still works
  rescue_from OtherError, use: Servus::Support::Errors::NotFoundError
end

obie and others added 4 commits November 20, 2025 07:03
This feature allows rescue_from to accept a block for custom error
handling, enabling services to:
- Return success despite exceptions
- Provide custom error messages
- Specify custom error types dynamically

The block is executed in a special context that provides success() and
failure() methods, giving full control over the response while maintaining
backward compatibility with existing non-block usage.

Example:
  rescue_from ActiveRecord::RecordInvalid do |e|
    failure("Failed to save: #{e.message}")
  end

  rescue_from NetworkError do |e|
    # Can recover from error and return success
    success({ recovered: true, fallback_used: true })
  end
Required for CI build to pass after modifying the gem structure
Appeasing the rubocop.
@sebscholl sebscholl merged commit 3d8d56e into zarpay:main Nov 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants