正常在實作 Rails 的 show action 時都會是:

@post = Post.find(params[:id])

根據傳入的 id 用 find 去找到物件,但若沒有這個 id 的紀錄呢?就會跑出 ActiveRecord::RecordNotFound 的錯誤,是錯誤喔不是 warning 而已

但其實這事情也不是挺嚴重,可能就不小心打錯 ID 或是被爬蟲亂爬導致,不算是 bug,只是沒有特別處理(尤當裝 rollbar 後,一直累計噴錯也不是辦法...)

那 rescue_from 是 ActiveController 裡面非常有用的一個函式,可以在一個 controller 的範圍內將某個 error 都 catch 起來統一處理,尤其是 ActiveRecord::RecordNotFound 這個~

class PostController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  private
  def record_not_found
    message = "Post with ID #{params[:id]} not found."
    logger.error message
    redirect_to not_found_url, info: message
  end
end

依照上述作法,當遇到 ActiveRecord::RecordNotFound 時就會自動記錄哪個 id 找不到 Post,並 redirect 到相對應告知找不到記錄的頁面。當然 rescue_from 本身也有 block 供使用,可以改成:

class PostController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found do |exception|
    message = "Post with ID #{params[:id]} not found."
    logger.error message
    redirect_to not_found_url, info: message
  end
end

如果是一般自己寫的 class 想要 handle 特殊例外狀況的話~可以直接 mixin ActiveSupport::Rescuable 就好

class Foo
  include ActiveSupport::Rescuable
end