Ruby 异常处理
Ruby 具有一些可用于脚本和面向对象的应用程序的强大特性。其中一个特性是 Ruby 的异常处理。清单 12 包含使用 Ruby 的异常处理机制的示例。
清单12:rubyExceptions.rb
=begin
This script is similar to Listing 10, but demonstrates Ruby exception handling
using functionality originally demonstrated in Listing 10.
=end
fileName = ARGV.to_s
#obtain file name if not provided on command-line
if fileName.size < 1
print "Enter init.ora path and name: "
fileName = gets.chomp!
end
#ensure something has been provided for file name
begin
if fileName.size < 1
raise ArgumentError, "No valid file name provided" + "n"
end
rescue ArgumentError => argErr
print argErr
raise # re-raise this exception and force script termination
end
#get file contents
begin #Begin exception handling block for file I/O
theFile = File.new(fileName, "r")
text = theFile.read
theFile.close
rescue IOError
print "I/O Error: Problem accessing file " + fileName + "n"
exit
rescue Errno::ENOENT
print "ENOENT: Cannot find file " + fileName + "n"
exit
rescue Errno::EPERM
print "EPERM: Insufficient rights to open " + fileName + "n"
raise
rescue Exception # Catch-all: More exceptions captured than with "rescue" alone
print "Generic error rescued (captured) during file I/O attempt." + "n"
raise
else
print "Good news! There was no problem with file I/O for " + fileName + "n"
ensure
print "Good or bad, file handling attempt is now complete!n"
end #End exception handling block for file I/O
#obtain text string for regular expression
print "Enter regular expression pattern: "
pattern = gets.chomp!
begin #Begin exception handling block for regular expression
regExp = Regexp.new(pattern)
rescue RegexpError
print "Problem with regular expression " + regExp.to_s + "n"
exit # Nothing to be done with a bad regular expression
ensure
print "Regular expression evaluated was: " + regExp.to_s + "n"
end #End exception handling block for regular expression
puts text.scan(regExp)
|
清单 12 演示了使用 begin 关键字标记可以引发(抛出)异常的代码块的起始位置。该清单中使用关键字 raise 供脚本引发(抛出)自己的异常。关键字 rescue 多次出现,与 Java 的 catch 关键字类似。Ruby 的 ensure 关键字与 Java 的 finally 关键字类似,在该代码清单中用于执行功能,无论是否遇到异常。
如清单 12 所示,Ruby 还支持 else 关键字涵盖以下情况下应该执行的功能:如果未针对由 begin 和 end 指示的特定代码块抛出任何异常。代码清单的注释进一步解释了 Ruby 的异常处理功能。
图 11 显示了运行清单 12 中的脚本三次的结果。第一次运行该脚本时,故意提供了一个未知的文件名以调用文件处理异常处理。第二次运行该脚本时用正确的文件名演示 else 块的执行,并允许执行转至与正则表达式处理相关的代码块。第二次执行该脚本时,提供了一个错误的表达式以演示 RegexpError 的处理。第三次运行该脚本时演示了脚本的完整运行,不引发异常。所有这三次运行都演示了 ensure 块的执行,因为无论是否引发(抛出)异常,所有异常处理过程中始终调用该块。
|
图11:正在运行的 Ruby 异常 |
Ruby DBI 异常处理。 最后一部分介绍了 Ruby 异常处理。Ruby/DBI 提供了自己的异常处理层次结构,如清单 13 所示。实际上,较常见的是只捕获“database catch all”异常 DBI::DatabaseError 并访问清单 13 中所显示的属性,以打印出数据库错误代码和错误消息。
清单13:rubyDbExceptions.rb
=begin
Listing13-rubyDbExceptions.rb
This script demonstrates the use of exceptions with DBI::DatabaseError
and database-related exception classes that inherit from DBI::DatabaseError.
Often, it is enough to capture DatabaseError, but this example shows all
of the inherited exception classes. DatabaseError is rescued last so that
a more particular database-related exception might be rescued first.
This "try" block of this code includes an "infinite" while loop that will
open connections without closing them until a DBI::DatabaseError is forced.
=end
require 'dbi'
begin
counter = 0
while 0 # "infinite" loop because 0 resolves to "true" for Ruby conditional
dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
counter += 1
puts "DB Connection #" + counter.to_s + "n"
#Intentionally NOT closing with dbh.close to force DatabaseError.
end
rescue DBI::DataError => dataErr
dbh.rollback
puts "DB error due to problem with data"
puts "Error Code: #{dataErr.err}"
puts "Error Message: #{dataErr.errstr}"
puts "DB rollback.n"
rescue DBI::IntegrityError => integErr
# Example: Trying to insert same value for unique column twice.
dbh.rollback
puts "DB error due to integrity problem."
puts "Error Code: #{integErr.err}"
puts "Error Message: #{integErr.errstr}"
puts "DB rollback.n"
rescue DBI::InternalError => internErr
dbh.rollback
puts "DB error database internal error."
puts "Error Code: #{internErr.err}"
puts "Error Message: #{internErr.errstr}"
puts "DB rollback.n"
rescue DBI::NotSupportedError => notSuppErr
dbh.rollback
puts "DB feature not supported."
puts "Error Code: #{notSuppErr.err}"
puts "Error Message: #{notSuppErr.errstr}"
puts "DB rollback.n"
rescue DBI::OperationalError => opErr
dbh.rollback
puts "DB error due to problems with operation of database."
puts "Error Code: #{opErr.err}"
puts "Error Message: #{opErr.errstr}"
puts "DB rollback.n"
rescue DBI::ProgrammingError => dbProgErr
# Example: Bad column name in SQL statement.
dbh.rollback
puts "DB error due to programming problem.n"
puts "Error Code: #{dbProgErr.err}"
puts "Error Message: #{dbProgErr.errstr}"
puts "DB rollback.n"
rescue DBI::DatabaseError => dbErr
# Catch-all for all database exceptions.
dbh.rollback
puts "Database exception encountered."
puts "Error Code: #{dbErr.err}"
puts "Error Message: #{dbErr.errstr}"
puts "DB rollback."
rescue DBI::InterfaceError => ifError
dbh.rollback
puts "Problem with DBI interface encountered."
rescue RuntimeError
dbh.rollback
puts "Unknown error (not DB or DBI) encountered."
else
puts "DB commit.n"
dbh.commit
ensure
puts "Disconnecting database handler."
dbh.disconnect
end
|