RecordNotFound Exception

by winson, about 1 year ago.

我最近聽過對於Ruby/Rails最有趣的評論是: Ruby/Rails除了簡潔之外,看不出還有什麼優點。

好吧,那就捲起袖子從最簡潔、最可愛的Dynamic Finder以及衍伸的例外處理來看好了。

因為Dynamic Finder實在是太可愛了,所以無處不在,例如:

# Very simple example

def show
  @bug = Bug.find(params[:id])
  @page_title = "About this bug" 
end
這段程式看起來不錯,實則不然,萬一找不到蟲,那怎麼辦呢?這有幾種處理方式:

解法一、邏輯判斷:

def show
  @bug = Bug.find(params[:id])
  @page_title = "About this bug" 
  unless @bug
    flash[:error] = 'This bug does not exist.'
    render :action => '404'
  end
end
我真喜歡unless,寫它的程式跟寫詩一樣,但千萬別相信Finder找不到資料一定傳回Nil,因此:

解法二、還是邏輯判斷:

def show
  if Bug.exists?(params[:id])
    @bug = Bug.find(params[:id])
    @page_title = "About this bug" 
  else
    flash[:error] = 'This bug does not exist.'
    render :action => '404'
  end
end
用Model.exits?的好處在於,找到資料給你True,找不到給你False,比較精確一點,不過這就不像詩了;或者你也可以:

解法三、例外處理:

def show
  @bug = Bug.find(params[:id])
  @page_title = "About this bug" 
  rescue ActiveRecord::RecordNotFound
    flash[:error] = 'This bug does not exist.'
    render :action => '404'
end
用rescue ActiveRecord::RecordNotFound是比較保險,而且程式的可讀性比較高。

這幾種解法麻煩的地方在於,只要你用Finder就必須去做額外的判斷處理,有沒有可以一次處理掉,而不需要每次都做額外處理呢?

當然有,而且這正是物件導向的好處。

解法四、在ApplicationController一次搞定:

protected

def rescue_action_in_public(exception)
  case exception
  when ActiveRecord::RecordNotFound
    render_404
  else
    render_500
  end
end
從User的角度來看,大致上只要區分”找不到資料”以及”系統出錯”兩種,所以我把RecordNotFound用一種方式處理,其他則用另一種方式處理,姑且稱為render_500好了。

至於rescue_action_locally暫時也沿用rescue_action_in_public好了,像這樣:

def rescue_action_locally(exception)
  rescue_action_in_public(exception)
end
當然你也可以直接Override rescue_action,如此一來絕大多數的例外或錯誤,都不會顯示在console裡頭,這樣反而造成困擾。

回憶一下之前的Missing Route on Rails,那時候說:

簡單寫一個404要用的網頁,放在’your_controller’的view裡頭,檔名是404.rhtml即可。至於404的action就別理它了,反正會先去找view。
沒錯,這裡也可以直接沿用,因此我的render_404可以這樣處理:
private

def render_404
  @page_title = '404 NOT FOUND'
  render :template => 'your_controller/404'
end
那麼,render_500該怎麼做呢?依樣畫葫蘆,只要添加一個500.rhtml的View,並改用另一張圖片,或學Twitter放一隻貓就好:
def render_500
  @page_title = '500 ERROR'
  render :template => 'your_controller/500'
end
於是系統出錯的時候,就會看到一隻貓不知所措、玩著電腦的樣子:


  • Posted in ActiveRecord, on Monday, June 04, 2007, at 09:26 AM.