12 - rescue exception
異常處理在開發過程中時常可見,舉例來說 Rails 中找不到對應的 routing 的時候則會丟出 Routing Error
,或者是在特定的程式碼中手動加入 raise
來丟出 Exception
1 2 3 4 5 6
| def validate_user if user.blank? raise "User is #{I18n.t('errors.messages.blank')}" end end
|
raise 起來後,我們可以透過 rescue
來處理 exception,並記錄於 logger 或者是通知第三方(Bugsnag)串接 slack 提醒都是可行的做法。
1 2 3 4 5 6 7 8 9 10
| def valid? validate_user validate_email validate_device
true rescue => e Bugsnag.notify e false end
|
註: 內建的 Error 有太多種類,詳情可以直接參考文件 https://ruby-doc.org/core-2.2.0/Exception.html
rescue 後也可以接對應的 Error 來做對應的事情。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class ApiService def initialize(url) @url = url
get_some_api_reponses rescue Net::ReadTimeout => e Bugsnag.notify(e) end
def get_some_api_reponses end end
|
通常 rescue
一開始寫的時候可能不常直接想到需要在什麼情況加入,對應的 Error 也寫的不清不楚,直接 e 全部 rescue 起來。不過從串接第三方噴出 exception 的通知後,再回來思考像是 api runtime 時間過長、import csv 需要 retry 的加入等等情況下,不只紀錄 log,還有能將噴錯時做對應的措施也是重要的一環。
與 rescue
相似的還有用在 controller 的 rescue_from
例外處理,通常我們在 user show 頁面很常會透過 params id 來找 user,但如果沒有 id 時,就會跑出 ActiveRecord::RecordNotFound
的錯誤。
1
| @user = User.find(params[:id])
|
這時,我們可以在 Controller 內加上 rescue_from
來處理,也可以寫成 block 的兩種方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class UserController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, with: :notify_record_not_found
private
def notify_record_not_found e = "User id:#{params[:id]} not found." Bugsnag.notify(e) end end
class UserController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, with: :notify_record_not_found do |_exception| e = "User id:#{params[:id]} not found." Bugsnag.notify(e) end
end
|