You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ruby类中捕获所有异常?附示例代码

Ruby类全局异常捕获的正确实现方式

嘿,我来帮你搞定这个Ruby全局异常捕获的需求~你之前写的代码其实有个小问题:rescue不能直接放在类定义的顶层,它必须包裹在begin...end块、方法内部,或者作为方法的修饰符来使用。下面给你两种靠谱的实现方案,满足你让子类方法自动捕获异常的需求:

方案一:用Mixin模块实现(推荐,更灵活)

这种方式用Ruby的模块混入特性,能给任意类添加异常捕获能力,不受单继承限制:

module ExceptionHandler
  def self.included(base)
    base.extend(ClassMethods)
    base.class_eval do
      @wrapped_methods = Set.new
    end
  end

  module ClassMethods
    # 钩子方法:当类新增实例方法时自动触发
    def method_added(name)
      # 避免重复包装方法,跳过safe_wrap本身
      return if @wrapped_methods.include?(name) || name == :safe_wrap

      @wrapped_methods.add(name)
      original_method = instance_method(name)
      # 重新定义方法,用异常捕获逻辑包装原方法
      define_method(name) do |*args, &block|
        safe_wrap do
          original_method.bind(self).call(*args, &block)
        end
      end
    end
  end

  # 通用异常捕获逻辑
  def safe_wrap
    yield
  rescue => e
    puts "Error!!! 异常信息:#{e.message}"
  end
end

# 使用示例
class ServiceA
  include ExceptionHandler

  def say_hello
    # 模拟抛出异常
    raise "数据库连接失败"
  end
end

ServiceA.new.say_hello # => Error!!! 异常信息:数据库连接失败

方案说明

  • 模块通过included钩子给目标类添加类方法,method_added会在类新增实例方法时自动触发,把原方法包装进异常捕获逻辑里
  • 用Set记录已包装的方法,避免重复包装导致死循环
  • 你可以根据需求修改safe_wrap里的捕获逻辑,比如记录日志、返回默认值等

方案二:用父类继承实现

如果你的服务类本来就有继承关系,也可以用父类统一实现异常捕获:

class BaseService
  def self.method_added(name)
    return if @wrapped_methods&.include?(name) || name == :handle_exception

    @wrapped_methods ||= Set.new
    @wrapped_methods.add(name)
    original_method = instance_method(name)

    define_method(name) do |*args, &block|
      handle_exception do
        original_method.bind(self).call(*args, &block)
      end
    end
  end

  def handle_exception
    yield
  rescue => e
    puts "Error!!!"
  end
end

# 使用示例
class ServiceA < BaseService
  def say_hello
    # 模拟异常
    error_code_here # 这里会抛出NameError异常
  end
end

ServiceA.new.say_hello # => Error!!!

方案说明

  • 父类BaseService的method_added钩子会自动包装所有子类的实例方法
  • 子类只需要继承BaseService,不需要额外写任何捕获代码,方法抛出异常时会自动触发父类的handle_exception逻辑

内容的提问来源于stack exchange,提问作者Dean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:36:02