我似乎无法找到有关自定义异常类多的信息。
我所知道的
你可以声明自定义错误类,并让它继承StandardError
,所以它可以rescue
d:
class MyCustomError < StandardError
end
这允许您使用,以提高它:
raise MyCustomError, "A message"
后来,当抢救获取信息
rescue MyCustomError => e
puts e.message # => "A message"
我不知道
我想给我的例外中的某些自定义字段,但我想继承message
从父类属性。 我发现阅读关于这个主题是@message
不是异常类的实例变量,所以我很担心我的遗产将无法正常工作。
谁能给我更多的细节吗? 我将如何实现与自定义错误类object
的属性? 是下列正确的是:
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
将它的工作,如果确实如此,这是做事的正确方法是什么?
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 Exception
与rescue MyCustomError
,看看为什么它是一个不好的风格在Ruby中`急救异常=> e`? 。
鉴于什么的红宝石核心文档Exception
,使所有其他错误继承,有关规定#message
返回调用exception.to_s的结果。 通常这将返回异常的消息或名称。 通过提供to_str方法,例外同意使用其中的字符串的预期。
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
我会选择重新定义to_s
/ to_str
或初始化。 这里我们想知道,在大部分人类可读的方式,当外部的服务没有做到的事情的例子。
注意:下面的第二个策略采用导轨漂亮串的方法,如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策略
这是最接近我在轨使用实现的策略。 如上所述,它使用demodualize
, underscore
,和humanize
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
演示工具
这是显示上述实施救援和信息演示。 该类提高例外是假的API来Cloudinary。 只转储上述策略之一到你的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
你的想法是对的,但是你把它的方式是错误的。 它应该是
raise MyCustomError.new(an_object, "A message")
我想要做类似的事情。 我想传递一个对象来#NEW并具有基于传递的对象的一些处理的消息集。 以下作品。
class FooError < StandardError
attr_accessor :message # this is critical!
def initialize(stuff)
@message = stuff.reverse
end
end
begin
raise FooError.new("!dlroW olleH")
rescue FooError => e
puts e.message #=> Hello World!
end
需要注意的是,如果你不声明attr_accessor :message
那么它将无法工作。 解决OP的问题,你也可以将消息传递作为额外的参数和存储你喜欢的东西。 关键部分出现覆盖#message。