Latest web development tutorials

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.. #抛出异常
 
rescue [ExceptionType = StandardException] #捕获指定类型的异常 缺省值是StandardException
 $! #表示异常信息
 $@ #表示异常出现的代码位置
else #其余异常
 ..
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 
   #.. 过程
   #.. 抛出异常
rescue 
   #.. 处理错误 
ensure 
   #.. 最后确保执行
   #.. 这总是会执行
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 
   #.. 过程 
   #.. 抛出异常
rescue 
   #.. 处理错误
else
   #.. 如果没有异常则执行
ensure 
   #.. 最后确保执行
   #.. 这总是会执行
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
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 throw 后匹配将被执行的 catch
end

或

throw :lablename condition
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 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: ")
   # ..
   # 处理信息
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
    # 写出数据 ...
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.