I can't seem to find much information about custom exception classes.
What I do know
You can declare your custom error class and let it inherit from StandardError
, so it can be rescue
d:
class MyCustomError < StandardError
end
This allows you to raise it using:
raise MyCustomError, "A message"
and later, get that message when rescuing
rescue MyCustomError => e
puts e.message # => "A message"
What I don't know
I want to give my exception some custom fields, but I want to inherit the message
attribute from the parent class. I found out reading on this topic that @message
is not an instance variable of the exception class, so I'm worried that my inheritance won't work.
Can anyone give me more details to this? How would I implement a custom error class with an object
attribute? Is the following correct:
class MyCustomError < StandardError
attr_reader :object
def initialize(message, object)
super(message)
@object = object
end
end
And then:
raise MyCustomError.new(anObject), "A message"
to get:
rescue MyCustomError => e
puts e.message # => "A message"
puts e.object # => anObject
will it work, and if it does, is this the correct way of doing things?
I wanted to do something similar. I wanted to pass an object to #new and have the message set based on some processing of the passed object. The following works.
Note that if you don't declare
attr_accessor :message
then it will not work. Addressing the OP's issue, you could also pass the message as an additional argument and store anything you like. The crucial part appears to be overriding #message.Given what the ruby core documentation of
Exception
, from which all other errors inherit, states about#message
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
I would opt for redefining
to_s
/to_str
or the initializer. Here is an example where we want to know, in a mostly human readable way, when an external service has failed to do something.NOTE: The second strategy below uses the rails pretty string methods, such as
demodualize
, which may be a little complicated and therefore potentially unwise to do in an exception. You could also add more arguments to the method signature, should you need.Overriding #to_s Strategy not #to_str, it works differently
Console Output
Overriding #initialize Strategy
This is the strategy closest to implementations I've used in rails. As noted above, it uses the
demodualize
,underscore
, andhumanize
ActiveSupport
methods. But this could be easily removed, as in the previous strategy.Console Output
Demo Tool
This is a demo to show rescuing and messaging of the above implementation. The class raising the exceptions is a fake API to Cloudinary. Just dump one of the above strategies into your rails console, followed by this.
raise
already sets the message so you don't have to pass it to the constructor:I've replaced
rescue Exception
withrescue MyCustomError
, see Why is it a bad style to `rescue Exception => e` in Ruby?.Your idea is right, but the way you call it is wrong. It should be