我不理解避免DoubleRenderError的代码

时间:2011-09-28 19:40:24

标签: ruby-on-rails

official page有这个片段:

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

的必要性

3 个答案:

答案 0 :(得分:2)

这是一个非常糟糕的例子。我真的反对and return短路方法,因为很多人不明白这意味着什么,而且除非你小心注意,否则它很容易被忽视。

更好的方法是描述你有明确if语句的地方,它突破了两种可能性。我将进一步将此全部折叠为一个render调用,其中提前确定了action参数:

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调用。

答案 1 :(得分:1)

他们 实际上都是等同的。你的例子碰巧用最不直观的版本。不知道为什么,但这种风格是我在Rails示例中经常看到的。

基本上,and是一个布尔运算符,具有非常低的绑定优先级,因此像expression_a and expression_b这样的行将导致expression_a被评估,然后,只要它没有评估为nilfalse,它会评估expression_b。由于render返回......好,非错误的东西 - 不知道究竟是什么......你的例子的行为与render whatever; return完全相同(或者用换行符代替分号,就像在第二个片段。

就个人而言,我更喜欢第三个片段,带有if / else块(不需要and return),因为无论如何它都在函数的末尾。它显而易见的是它的作用,我喜欢在我的代码中。

希望这有帮助!

答案 2 :(得分:1)

在第一个代码段中,如果and return不存在,并且@book.special?是真的,那么您将获得DoubleRenderError。那是因为render调用都将被执行。

考虑到这一点,所有的片段都是等效的,因为它们会阻止render被调用两次。另外,在最后一个片段中,不需要and return,因为render中只有一个会被调用。