Exceptions and execution are constantly integrated. On the off chance that you open a record that doesn't exist and you don't deal with it legitimately, at that point your program is viewed as low quality.
If a special case happens, the program stops. Exemptions are utilized to deal with different sorts of mistakes that can happen amid program execution, so make proper move without giving the program a chance to stop totally.
Ruby gives an ideal instrument to dealing with exemptions. We can connect code that may toss a special case to the begin/end square and utilize the rescue condition to tell Ruby precisely what sort of exemption to deal with.
Everything from begin to rescue is secured. In the event that a special case happens amid the execution of the code square, control goes to the square between rescue and end.
For each rescue condition in the begin square, Ruby contrasts the tossed special case and every parameter thusly. In the event that the exemption named in the salvage proviso is equivalent to the at present tossed special case type, or the parent of the exemption, the match is fruitful.
If the exemption does not coordinate the majority of the predefined blunder types, we can utilize a else provision after all rescue statements.
The above example runs the output as . As you can see, STDIN replaces file because open failed.
Using the retry statement
You can use the rescue block to catch exceptions and then use the retry statement to execute the begin block from the beginning.
The following is the process flow:
- An exception occurred while opening.
- Jump to rescue. Fname is reassigned.
- Jump through retry to the beginning of begin.
- This file was successfully opened.
- Continue the basic process.
Note: If the renamed file does not exist, this example code will try infinitely. So use retry with caution when handling exceptions.
Use the raise statement
You can throw an exception using the raise statement. The following method throws an exception when called. Its second message will be output.
The first structure essentially rethrows the present special case (and tosses a RuntimeError if there is no present exemption). This is utilized in exemption handlers that need to translate special cases before going in special cases.
The second structure makes another RuntimeError exemption, setting its message to the given string. The special case is tossed to the call stack.
The third structure makes a special case with the main contention and after that sets the related message to the second contention.
The fourth structure is like the third structure, and you can include any extra restrictive articulations, (for example, unless) to toss a special case.
The above example runs the output as:
I am before the raise . I am rescued. I am after the begin block.
Another example of a raise usage:
The above example runs the output as:
A test exception. ["main.rb:4"]< /pre>
Using the ensure statement
Sometimes, whether or not you throw an exception, you need to ensure that some processing is done at the end of the code block. For example, you might have opened a file when you entered, and when you exit the block, you need to make sure to close the file.The
ensure clause is this. Ensure is placed after the last rescue clause and contains a block of code that is always executed when the block terminates. It doesn't matter whether it terminates with a block, whether it throws and handles an exception, or if it terminates with an uncaught exception. The ensure block will always run.
Syntaxbegin #.. Process #.. Throw an exception Span> rescue #.. Handling errors ensure #.. Finally make sure to execute Span> #.. This will always be performed end
Instancebegin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ensuring execution" end
The above example runs the output as:A test exception. ["main.rb:4"] Ensuring execution
Use the else statement
If the else clause is provided, it is usually placed after the rescue clause, before any ensure.The body of the
else clause is only executed if the code body does not throw an exception.
Syntaxbegin #.. Process #.. Throw an exception Span> rescue #.. Handling errors else #.. Execute if there are no exceptions ensure #.. Finally make sure to execute Span> #.. This will always be performed end
Instancebegin # Throw 'A test exception.' puts "I'm not raising exception" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Congratulations-- no errors!" ensure puts "Ensuring execution" end
The above example runs the output as:I'm not raising exception Congratulations-- no errors! Ensuring execution
Use the $! variable to catch the thrown error message.
Catch and Throw
Raise and rescue exception mechanisms can abandon execution when an error occurs, and sometimes need to jump out of some deeply nested structures during normal processing. At this point catch and throw come in handy.
catch defines a block that uses the given name (which can be a Symbol or a String) as a label. The block will execute normally until it encounters a throw.
grammarthrow :lablename #.. This will not be executed catch :lablename do #.. Encounter one throw After the match will be executed catch end or throw :lablename condition #..This will not be executed after a throw is encountered. catch :lablename do #.. The match will be executed after a throw is encountered catch end
In the example below, if the user types '!' to respond to any prompts, use a throw to terminate the interaction with the user.
Instancedef promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # Processing information end promptAndGet("Name:")
The above program requires human interaction and you can try it on your computer. The output of the above example runs as follows:Name: Ruby on Rails Age: 3 Sex: ! Name:Just Ruby
Ruby's standard classes and modules throw exceptions. All exception classes form a hierarchy, including the top Exception class. The next layer is in seven different types:
Fatal is another exception in this layer, but the Ruby interpreter only uses it internally.
ScriptError and StandardError have some subclasses, but we don't need to know these details here. The most important thing is to create our own exception classes, which must be subclasses of the class Exception or its children.
Let's see an example:
Now, look at the example below, which will use the above exception:
The most important line here is raise FileSaveError.new($!). We call raise to indicate that an exception has occurred, passing it to a new instance of FileSaveError , which caused the data to fail due to a specific exception.