iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0

12 - rescue exception

異常處理在開發過程中時常可見,舉例來說 Rails 中找不到對應的 routing 的時候則會丟出 Routing Error,或者是在特定的程式碼中手動加入 raise 來丟出 Exception

  # 驗證 params[:user]
  def validate_user
    if user.blank?
      raise "User is #{I18n.t('errors.messages.blank')}"
    end
  end

raise 起來後,我們可以透過 rescue 來處理 exception,並記錄於 logger 或者是通知第三方(Bugsnag)串接 slack 提醒都是可行的做法。

  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 來做對應的事情。

  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 的錯誤。

  @user = User.find(params[:id])

這時,我們可以在 Controller 內加上 rescue_from 來處理,也可以寫成 block 的兩種方式。

  # (1)
  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

  # (2)
  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

My blog


上一篇
冒險村11 - frozen_string_literal
下一篇
冒險村13 - migration notes
系列文
冒險村-30 Day Ruby on Rails Tips Challenge30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言