2011-09-28 38 views
4

official page有此片段的代碼:我不明白,避免DoubleRenderError

def show 
    @book = Book.find(params[:id]) 
    if @book.special? 
    render :action => "special_show" and return 
    end 
    render :action => "regular_show" 
end 

爲什麼不是這等同?

def show 
    @book = Book.find(params[:id]) 
    if @book.special? 
    render :action => "special_show" 
    return 
    end 
    render :action => "regular_show" 
end 

或者,爲什麼不使用它?

def show 
    @book = Book.find(params[:id]) 
    if @book.special? 
    render :action => "special_show" and return 
    else 
    render :action => "regular_show" 
    end 
end 

我不明白render ... and return

回答

1

他們都是其實都是等效的。你的例子恰好與最不直觀的明顯版本一起使用。不知道爲什麼,但這種風格是我經常在Rails例子中看到的。

從本質上講,and是非常低優先級的結合布爾邏輯運算符,所以像expression_a and expression_b一行將導致expression_a進行評估,然後,只要它不計算爲nilfalse,它會評估expression_b 。由於render返回...好,非真的東西 - 不知道是什麼,確切地...你的例子的行爲完全像render whatever; return(或者換行符而不是分號,就像第二個片段中那樣)。

就我個人而言,我更喜歡第三個代碼段,其中包含if/else塊(不需要and return,因爲它總是處於函數的末尾)。它在你的臉上顯而易見,它在我的代碼中很喜歡。

希望這會有所幫助!

2

的需要這是一個非常壞的榜樣。我真的反對and return短路的方法,因爲很多人不明白它的含義,而且除非你特別注意,否則它很容易被忽略。

更好的方法是描述哪裏有明確的if聲明,它突出了兩種可能性。我會去一個進一步摺疊所有到一個單一的render調用與確定的時間提前行動的說法是:

def show 
    @book = Book.find(params[:id]) 

    # Determine the template to be used for this action 
    render_action = @book.special? ? 'special_show' : 'regular_show' 

    # Render the appropriate template 
    render(:action => render_action) 

rescue ActiveRecord::RecordNotFound 
    render(:action => 'not_found', :status => :not_found) 
end 

也是從這個例子裏缺了陷阱的find呼叫可生產如果一個異常記錄未找到。這是一個常見的視線,我很確定大多數人完全忘記了它。請記住,即使在收到錯誤的請求時,您也不應該在精心設計的應用程序中渲染500個「服務器錯誤」。

避免雙重渲染錯誤的最簡單方法畢竟是隻有一個render調用。

+0

第一次渲染後的回報如何?那會不對? – Geo

+1

不要從'ActiveRecord :: RecordNotFound'救援。 Rails默認使用404頁面([source](https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb))。 – molf

1

在第一個片段中,如果and return不存在,並且@book.special?是真的,您將得到一個DoubleRenderError。這是因爲兩個render調用都會​​被執行。

考慮到這一點,所有的片段都是相同的,因爲它們會阻止render被調用兩次。另外,在最後一個片段中,不需要and return,因爲render中只有一個會被調用。