首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Ruby自定义错误类:消息属性的继承

Ruby自定义错误类:消息属性的继承
EN

Stack Overflow用户
提问于 2013-04-19 22:11:14
回答 4查看 68.4K关注 0票数 98

我似乎找不到太多关于自定义异常类的信息。

我所知道的

您可以声明您的自定义error类,并让它从StandardError继承,因此它可以是rescued:

class MyCustomError < StandardError
end

这使您可以使用以下命令来引发它:

raise MyCustomError, "A message"

然后,在解救的时候得到这个信息

rescue MyCustomError => e
  puts e.message # => "A message"

我不知道什么

我想给我的异常提供一些自定义字段,但我想从父类继承message属性。我在读on this topic时发现@message不是exception类的实例变量,所以我担心我的继承无法工作。

有人能给我更多的细节吗?如何实现具有object属性的自定义error类?以下内容是否正确:

class MyCustomError < StandardError
  attr_reader :object
  def initialize(message, object)
    super(message)
    @object = object
  end
end

然后:

raise MyCustomError.new(anObject), "A message"

要获得以下信息:

rescue MyCustomError => e
  puts e.message # => "A message"
  puts e.object # => anObject

它会起作用吗?如果起作用,这是正确的做事方式吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-04-19 23:31:10

raise已经设置了消息,所以您不必将其传递给构造函数:

class MyCustomError < StandardError
  attr_reader :object

  def initialize(object)
    @object = object
  end
end

begin
  raise MyCustomError.new("an object"), "a message"
rescue MyCustomError => e
  puts e.message # => "a message"
  puts e.object # => "an object"
end

我已经用rescue MyCustomError替换了rescue Exception,参见Why is it a bad style to rescue Exception => e in Ruby?

票数 127
EN

Stack Overflow用户

发布于 2016-08-20 18:02:08

鉴于所有其他错误都继承自Exception的ruby核心文档对#message的描述

返回调用exception.to_s的结果。通常会返回异常的消息或名称。通过提供to_str方法,异常同意在需要字符串的地方使用。

我会选择重新定义to_s/to_str或初始化器。下面是一个示例,我们希望以一种人类可读的方式知道外部服务何时做不到某件事。

注意:下面的第二个策略使用了rails的字符串方法,比如demodualize,这可能有点复杂,因此在异常中这样做可能是不明智的。如果需要,您还可以向方法签名添加更多参数。

覆盖#to_s策略而不是#to_str,它的工作方式不同

module ExternalService

  class FailedCRUDError < ::StandardError
    def to_s
      'failed to crud with external service'
    end
  end

  class FailedToCreateError < FailedCRUDError; end
  class FailedToReadError < FailedCRUDError; end
  class FailedToUpdateError < FailedCRUDError; end
  class FailedToDeleteError < FailedCRUDError; end
end

控制台输出

begin; raise ExternalService::FailedToCreateError; rescue => e; e.message; end
# => "failed to crud with external service"

begin; raise ExternalService::FailedToCreateError, 'custom message'; rescue => e; e.message; end
# => "failed to crud with external service"

begin; raise ExternalService::FailedToCreateError.new('custom message'); rescue => e; e.message; end
# => "failed to crud with external service"

raise ExternalService::FailedToCreateError
# ExternalService::FailedToCreateError: failed to crud with external service

覆盖#initialize Strategy

这是我在rails中使用过的最接近实现的策略。如上所述,它使用demodualizeunderscorehumanize ActiveSupport方法。但这可以很容易地删除,就像在之前的策略中一样。

module ExternalService
  class FailedCRUDError < ::StandardError
    def initialize(service_model=nil)
      super("#{self.class.name.demodulize.underscore.humanize} using #{service_model.class}")
    end
  end

  class FailedToCreateError < FailedCRUDError; end
  class FailedToReadError < FailedCRUDError; end
  class FailedToUpdateError < FailedCRUDError; end
  class FailedToDeleteError < FailedCRUDError; end
end

控制台输出

begin; raise ExternalService::FailedToCreateError; rescue => e; e.message; end
# => "Failed to create error using NilClass"

begin; raise ExternalService::FailedToCreateError, Object.new; rescue => e; e.message; end
# => "Failed to create error using Object"

begin; raise ExternalService::FailedToCreateError.new(Object.new); rescue => e; e.message; end
# => "Failed to create error using Object"

raise ExternalService::FailedCRUDError
# ExternalService::FailedCRUDError: Failed crud error using NilClass

raise ExternalService::FailedCRUDError.new(Object.new)
# RuntimeError: ExternalService::FailedCRUDError using Object

演示工具

这是一个演示,展示了上述实现的救援和消息传递。引发异常的类是Cloudinary的假API。只需将上述策略之一转储到您的rails控制台,然后执行以下操作。

require 'rails' # only needed for second strategy 

module ExternalService
  class FailedCRUDError < ::StandardError
    def initialize(service_model=nil)
      @service_model = service_model
      super("#{self.class.name.demodulize.underscore.humanize} using #{@service_model.class}")
    end
  end

  class FailedToCreateError < FailedCRUDError; end
  class FailedToReadError < FailedCRUDError; end
  class FailedToUpdateError < FailedCRUDError; end
  class FailedToDeleteError < FailedCRUDError; end
end

# Stub service representing 3rd party cloud storage
class Cloudinary

  def initialize(*error_args)
    @error_args = error_args.flatten
  end

  def create_read_update_or_delete
    begin
      try_and_fail
    rescue ExternalService::FailedCRUDError => e
      e.message
    end
  end

  private def try_and_fail
    raise *@error_args
  end
end

errors_map = [
  # Without an arg
  ExternalService::FailedCRUDError,
  ExternalService::FailedToCreateError,
  ExternalService::FailedToReadError,
  ExternalService::FailedToUpdateError,
  ExternalService::FailedToDeleteError,
  # Instantiated without an arg
  ExternalService::FailedCRUDError.new,
  ExternalService::FailedToCreateError.new,
  ExternalService::FailedToReadError.new,
  ExternalService::FailedToUpdateError.new,
  ExternalService::FailedToDeleteError.new,
  # With an arg
  [ExternalService::FailedCRUDError, Object.new],
  [ExternalService::FailedToCreateError, Object.new],
  [ExternalService::FailedToReadError, Object.new],
  [ExternalService::FailedToUpdateError, Object.new],
  [ExternalService::FailedToDeleteError, Object.new],
  # Instantiated with an arg
  ExternalService::FailedCRUDError.new(Object.new),
  ExternalService::FailedToCreateError.new(Object.new),
  ExternalService::FailedToReadError.new(Object.new),
  ExternalService::FailedToUpdateError.new(Object.new),
  ExternalService::FailedToDeleteError.new(Object.new),
].inject({}) do |errors, args|
  begin 
    errors.merge!( args => Cloudinary.new(args).create_read_update_or_delete)
  rescue => e
    binding.pry
  end
end

if defined?(pp) || require('pp')
  pp errors_map
else
  errors_map.each{ |set| puts set.inspect }
end
票数 11
EN

Stack Overflow用户

发布于 2013-04-19 22:20:05

你的想法是对的,但你说它的方式是错的。它应该是

raise MyCustomError.new(an_object, "A message")
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16106645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档