开发者

I don't understand the code for avoiding DoubleRenderError

The official page has this snippet:

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

Why isn't this equivalent?

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

Or, why isn't this used?

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

I don't understand the need for render ... and return


That's a really bad example. I'm really opposed to the and return method of short-circuiting because a lot of people don't understand what it means, and further, it's liable to be overlooked unless you're paying careful attention.

The better approach is as you describe where you have an explicit if statement that breaks out the two possibilities. I'd go one further to collapse this all into a single render call with the action argument identified ahead of time:

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

Also missing from the example was the trap for the find call which can produce an exception if the record isn't found. This is a common over-sight and I'm pretty sure most people forget about it entirely. Remember you shouldn't be rendering 500 "server error" in a well designed app even when receiving bad requests.

The easiest way to avoid a double render error is to have only one render call, after all.


They are in fact all equivalent. Your example just happened to go with the least intuitively obvious version. Not sure why, but that style is something I've seen frequently in Rails examples.

Essentially, and is a boolean operator with really low binding precedence, so a line like expression_a and expression_b will result in expression_a being evaluated, and then, as long as it didn't evaluate to nil or false, it'll evaluate expression_b. Since render returns... well, something non-false - don't know what, exactly ...your example behaves exactly like render whatever; return (or with a line break instead of the semicolon, like in the second snippet).

Personally, I prefer the third snippet, with the if/else block (which doesn't need the and return, 'cause it's at the end of the function anyway). It's in-your-face obvious what it does, and I like that in my code.

Hope this helps!


In the first snippet, if the and return was absent, and @book.special? was truthy, you would get a DoubleRenderError. That's because both the render calls would be executed.

With that in mind, all of the snippets are equivalent in that they will prevent render from being called twice. Also, in the last snippet, the and return is not needed since only one of the render's will ever get called.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜