Ruby exception
Exceptions and execution are always linked. If you open a file that does not exist, and not properly handle the situation, then your program is considered to be of low quality.
If an exception occurs, the program stops. Exception handling for all types of errors that may occur during program execution, so to take appropriate action, and will not let the program completely stopped.
Ruby provides a perfect mechanism for handling exceptions. We can attach code that might throw an exception, and userescueclauses to tell Ruby the perfect type of exception to be handled in thebegin / endblock.
grammar
begin #开始 raise/en #抛出异常 rescue [ExceptionType = StandardException] #捕获指定类型的异常 缺省值是StandardException $! #表示异常信息 $@ #表示异常出现的代码位置 else #其余异常 /en ensure #不管有没有异常,进入该代码块 end #结束
Tobegineverything from therescueis protected. If during the execution of the code block exception occurs, control will be passed between theendand the blockrescue.
Forbeginblock eachrescueclause, Ruby and the exception thrown in turn to each parameter comparison. If the rescue clause naming exception and exception type thrown by the same current, or is the parent class of the exception, the match was successful.
If the exception does not match any of the specified type of error, we can use anelseclause after allrescueclause.
Examples
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, "\n"
Examples of the above output is running. As you cansee,STDIN replace thefile,because theopenfailed.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Useretrystatement
You can use therescueblock to catch the exception, and then use theretrystatement block beginbeginfrom the beginning.
grammar
begin # 这段代码抛出的异常将被下面的 rescue 子句捕获 rescue # 这个块将捕获所有类型的异常 retry # 这将把控制移到 begin 的开头 end
Examples
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
The following is the process flow:
- An exception occurred when opened.
- Skip to rescue. fname be reassigned.
- Skip to the beginning begin by retry.
- The file is successfully opened.
- Continue the basic process.
Note: If the renamed file does not exist, this forces code unlimited attempts.So the exception handling, use cautionretry.
Useraisestatement
You can use theraisestatement throws an exception. The following method throws an exception when you call. Its second message will be output.
grammar
raise 或 raise "Error Message" 或 raise ExceptionType, "Error Message" 或 raise ExceptionType, "Error Message" condition
The first form simply re-throw the current exception (if there is no current exception is thrown a RuntimeError). This is used to explain before the incoming exception exception exception handler.
The second form creates a newRuntimeErrorexception, setting its message to the given string. After the call stack to throw the exception.
A third form of the first parameter to create an exception, then set the related messages as the second parameter.
The fourth form and the third form is similar, you can add any additional conditional statements (egunless)to throw an exception.
Examples
#!/usr/bin/ruby begin puts 'I am before the raise.' raise 'An error has occurred.' puts 'I am after the raise.' rescue puts 'I am rescued.' end puts 'I am after the begin block.'
Run the above example output is:
I am before the raise. I am rescued. I am after the begin block.
Another demonstrationraiseusage examples:
#!/usr/bin/ruby begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect end
Run the above example output is:
A test exception. ["main.rb:4"]
Ensurethe use of statements
Sometimes, regardless of whether an exception is thrown, you need to ensure that some process is completed at the end of the code block. For example, you might open a file at the time of entry, when you exit the block, you need to make sure to close the file.
ensureclause to do is this. ensure placed after the last rescue clause and contains a block termination code block is always executed. It is normal to exit the block, throw and handle exceptions whether, whether because of an uncaught exception terminates, none of theserelations,ensure block will always run.
grammar
begin #/en 过程 #/en 抛出异常 rescue #/en 处理错误 ensure #/en 最后确保执行 #/en 这总是会执行 end
Examples
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ensuring execution" end
Run the above example output is:
A test exception. ["main.rb:4"] Ensuring execution
Usingelsestatements
If theelseclause is provided, it is usually placed after therescueclause, before anyensure.
bodyelseclause is executed only when the body of code without throwing an exception.
grammar
begin #/en 过程 #/en 抛出异常 rescue #/en 处理错误 else #/en 如果没有异常则执行 ensure #/en 最后确保执行 #/en 这总是会执行 end
Examples
begin # 抛出 '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
Run the above example output is:
I'm not raising exception Congratulations-- no errors! Ensuring execution
Use $! Variable can catch the error message thrown.
Catch and Throw
raise and rescue exception mechanism can give up execution when an error occurs, sometimes you need to jump in the normal process of some deeply nested structure. At this point catch and throw come in handy.
catchdefines a given name (may be a Symbol or String) label as a block. Block is executed normally know encounters a throw.
grammar
throw :lablename #/en 这不会被执行 catch :lablename do #/en 在遇到一个 throw 后匹配将被执行的 catch end 或 throw :lablename condition #/en 这不会被执行 catch :lablename do #/en 在遇到一个 throw 后匹配将被执行的 catch end
Examples
The following example, if a user types '!' Respond to any prompt, use a throw to terminate interaction with the user.
def 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: ") # /en # 处理信息 end promptAndGet("Name:")
The above program requires human interaction, you can try on your computer. Run the above example output is:
Name: Ruby on Rails Age: 3 Sex: ! Name:Just Ruby
Exception class
Ruby's standard classes and modules thrown. All exception classes form a hierarchy, including the top of the inner Exception class. The next layer is seven different types:
- Interrupt
- NoMemoryError
- SignalException
- ScriptError
- StandardError
- SystemExit
Fatal is the layer of another exception, but the Ruby interpreter only use it internally.
ScriptError and StandardError have some sub-categories, but here we need to know these details. The most important thing is to create our own exception class, they must be a subclass of class Exception or its progeny.
Let's look at an example:
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
Now, look at the following example will be used in the above exceptions:
File.open(path, "w") do |file| begin # 写出数据 /en. rescue # 发生错误 raise FileSaveError.new($!) end end
Here, the most important line israiseFileSaveError.new ($!). We call raise schematically exception has occurred, it passed a new instance FileSaveError due to specific abnormalities caused by data write fails.