A custom exception is any class that extends Exception or a subclass of Exception.
In general, you should always extend StandardError or a descendant. The Exception family are usually for virtual-machine or system errors, rescuing them can prevent a forced interruption from working as expected.
# Defines a new custom exception called FileNotFound
class FileNotFound < StandardError
end
def read_file(path)
File.exist?(path) || raise(FileNotFound, "File #{path} not found")
File.read(path)
end
read_file("missing.txt") #=> raises FileNotFound.new("File `missing.txt` not found")
read_file("valid.txt") #=> reads and returns the content of the file
It's common to name exceptions by adding the Error suffix at the end:
ConnectionErrorDontPanicErrorHowever, when the error is self-explanatory, you don't need to add the Error suffix because would be redundant:
FileNotFound vs FileNotFoundErrorDatabaseExploded vs DatabaseExplodedError