iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
0
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 12

Day12: Ruby的例外處理(Exceptions):begin...rescue ...end

  • 分享至 

  • xImage
  •  

幾乎每個程式語言都有例外處理的功能,當程式在執行時,不免都會遇到非工程師預期的狀況發生,我們可以針對不同例外訊息設計不同的例外處理。

在Ruby例外處理的基本架構:

begin
  #程式碼正常執行的地方 (可能出現例外的程式碼)
rescue 
  #發生錯誤時執行的地方
end

當Ruby執行程式發生錯誤時,會丟出一個Error類別產生的例外物件並停止程式,各種錯誤類型用架構的方式歸納:


圖片來源:Programming Ruby book

有這麼多例外訊息的類別,要舉例可能舉不完,不過用起來大概像下面這種感覺:

begin 
  # 可能出現例外的程式碼
rescue SyntaxError
  # 出現SyntaxError時執行此行程式碼
rescue ArgumentError
  # 出現ArgumentError時執行此行程式碼
rescue RuntimeError
  # 出現RuntimeError時執行此行程式碼
end

所以可針對丟出的例外訊息,去處理該訊息的例外處理,當然最常見的還是SyntaxError, ArgumentErrorRuntimeError。如果沒有在rescue後特別寫哪種類別的話,任何的錯誤類別都會被rescue給抓到。

在舉例之前,我想先說說該如何用raise來產生例外處理。

raise

一般在簡單的程式碼,比較不會有例外處理的狀況發生,但為了舉例,我們也可以透過手動產生例外處理來觸發我們想要的結果,那我們就可以用raise method來執行。

raise是什麼?

The raise method is from the Kernel module. By default, raise creates an exception of the RuntimeError class.

raise是來自於Kernel這個module的method,"預設"會產生來自RuntimeError這個類別的exception實體。

既然是預設,代表我們一定可以自己寫raise method後會產生哪個類別的實體。

預設:RuntimeError

def raise_exception  
  puts '這邊是執行到raise之前'  
  raise '發生錯誤!'
  puts '這邊是執行到raise之後'  
end  
raise_exception  

印出

這邊是執行到raise之前
Traceback (most recent call last):
	1: from test.rb:18:in `<main>'
test.rb:15:in `raise_exception': 發生錯誤! (RuntimeError)
                                           #預設類別

指定其他類別(以ArgumentError為例)

def raise_exception  
  puts '這邊是執行到raise之前'  
  raise ArgumentError, '發生錯誤!'
  puts '這邊是執行到raise之後'  
end  
raise_exception  

印出

這邊是執行到raise之前
Traceback (most recent call last):
	1: from test.rb:18:in `<main>'
test.rb:15:in `raise_exception': 發生錯誤! (ArgumentError)
                                           #被指定類別 

begin...rescue...end

預設Exception

程式執行時先印出"發生例外之前",之後遇到raise發生例外,故去找rescue底下的程式碼並執行,印出"已處理例外"。

def raise_exception  
  begin
    puts '發生例外之前'  
    raise '發生例外!'     #沒指定Error類別,預設為RuntimeError
    puts '發生例外之後'
  rescue                 #預設RuntimeError,所有錯誤都會到這執行
    puts '已處理例外'
  end
end  
raise_exception 

# => 發生例外之前
#    已處理例外

指定錯誤類別

程式執行時先印出"發生例外之前",之後遇到raiseLoadError類別發生例外,因為已被指定是遇到LoadError產生的實體,rescue後並無指定要救援哪個類別,故印出"發生例外! (LoadError)"。

def raise_exception  
  begin
    puts '發生例外之前'  
    raise LoadError, '發生例外!'
    puts '發生例外之後'
  rescue
    puts '已處理例外'
  end
end  
raise_exception  

# => 發生例外之前
#    發生例外! (LoadError)

若要修正,只要將rescue後加入該發生例外訊息時的類別就可以了。

def raise_exception  
  begin
    puts '發生例外之前'  
    raise LoadError, '發生例外!'
    puts '發生例外之後'
  rescue LoadError
    puts '已處理例外'
  end
end  
raise_exception 

# => 發生例外之前
#    已處理例外

其實以上範例的beginend,可以被同時省略,只要留下rescue就可以正常執行,讓程式碼看起來更精簡,但對於金魚腦的我來說,為了方便未來能夠容易閱(理)讀(解),還是不會把它們省略。

def raise_exception  
    puts '發生例外之前'  
    raise LoadError, '發生例外!'
    puts '發生例外之後'
  rescue LoadError
    puts '已處理例外'
end  
raise_exception 

# => 發生例外之前
#    已處理例外

總結:

其實這個主題可以寫出非常多東西,目前只針對自己可能會用到的部分做說明,如果有興趣的朋友可以到參考資料看更多關於Exceptions的介紹。

  1. begin...rescue...end用來解決非預期的結果。
    • begin...rescue: 可能發生例外的程式碼
    • rescue...end: 發生錯誤時執行的程式碼
  2. 可針對丟出的例外訊息,去處理該訊息的例外處理。
  3. begin end可省略

參考資料:
Ruby Kernel
Ruby Exceptions
例外處理 Rescue Exception, Error Handling, Custom Error Pages
[Ruby] Error Handling(錯誤處理)
Ruby 的例外處理機制
Rails的錯誤處理機制begin、rescue和Exception

“The meaning of life is to find your gift. The purpose >of life is to give it away.”

– Pablo Picasso, Artist

本文同步發佈於: https://louiswuyj.tw/


上一篇
Day11: Ruby中的Getter及Setter?
下一篇
Day13: Ruby on Rails 的 .nil? .empty? .blank? .present?
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言