|
The image on the previous page is very useful because it will allow you to manage exceptions much better.So, when you need to raise a particular exception you can use one of the already predefined exceptions or define one of your own.
How to define your own?
Like you've learned in the previous chapter about inherited classes.
class FileWritingError < StandardError
attr_reader :reasonwhy
def initialize(reasonwhy)
@reasonwhy = reasonwhy
end
end
If you do,it's generally advisable to make it a subclass of the StandardError one or of one of it's children to ensure it's caught by default.
BEGIN - END exception handling
You can think of the term "handling" as like in "what" the program should do in case a certain error happens.
Think of clauses enclosed between BEGIN and END as if they were "case" statements...Ruby will select which one to process.
Raise and rescue will essentially cause abandoning execution.
begin
.... <- info that should be tested,processed
rescue LoadError, NameError => variable_to_receive_the_matched_expression
print "Error loading file " + variable_to_receive_the_matched_expression
rescue SignalException => variable_to_receive_the_matched_expression2
print "Interrupt conflict " + variable_to_receive_the_matched_expression
else ....(something to be done when no exceptions are raised; not required but indicated)
ensure .... (similar to the effect of else except it will always run;not required but indicated.
for example,if you were just processing a file, you could now make sure it gets closed after the code
in the begin - end block finished to run)
end
A rescue clause with no parameters defaults to StandardError.
In case the raised exception matches a parameter,Ruby will execute the corresponding rescue instructions and stops searching for others.Matching is made using the syntax parameter===$!
Ruby will search up the stack for an exception handler in the caller, then in the caller's caller and so on if an exception is either raised outside a being/end block or if no rescue clause matches.If no handle is found, not even at the topmost level, this will cause the program to terminate.
dailyentry = createentry()
whereto = createtodaypage()
begin
.... -> code here will start writing some data to file
rescue IOError
$stderr.puts “Failed posting daily blog entry due to disk error $!.”
waitminutes()
retry
end
Imagine you want to write a script to post blog entries on your Ruby site.Part of the code above could server such a purpose at least in concept...you "create" a new blog entry in a filed names after today's date, you start typing, you press save and bam!, you're slapped with an error because the server's hdd is full, or because it has developed a physical error on the sector you're trying to write...or god know what other reasons.
You instruct your program to "waitminutes" and then retry to post your entry.
Catch and throw methods
Catch specifies a block labeled with a name you choose (which can be a symbol or string).The block of code is executed until a "throw" instruction is encountered.Catch and throw are to be used when parsing through a complex code or data structure and for some reason or error encountered, going through the rest of the code is no longer necessary.
example of code from here
def prompt_and_get(prompt)
print prompt
res = readline.chomp
throw :quit_requested if res == "!"
res
end
catch :quit_requested do
name = prompt_and_get("Name: ")
age = prompt_and_get("Age: ")
sex = prompt_and_get("Sex: ")
# ..
# process information
end
"When Ruby encounters a throw, it zips back up the call stack looking for a catch
block with a matching symbol. When it finds it, Ruby unwinds the stack to that point
and terminates the block [...] If the throw is called with the optional second parameter,
that value is returned as the value of the catch."
- quoted from the same source as above
|