I do not understand the code to avoid 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 is this not equivalent?

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

Or, why is this not 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 do not understand the need for render ... and return

+4
source share
3 answers

They are actually all equivalent. Your example just went through with the least intuitively obvious version. Not sure why, but this style is what I often saw in Rails examples.

Essentially, and is a logical operator with a really low binding priority, so a string like expression_a and expression_b will evaluate expression_a , and then, until it evaluates to nil or false , it will evaluate expression_b . Since render returns ... well, something non-false - I donโ€™t know what exactly ... your example behaves exactly like render whatever; return render whatever; return (or with a line break instead of a semicolon, as in the second fragment).

Personally, I prefer the third fragment, with an if / else block (which does not need and return , because it is at the end of the function anyway). It is obvious in your face what he is doing, and I like it in my code.

Hope this helps!

+1
source

This is a really bad example. I am really against the short circuit and return method, because many people do not understand what this means, and in addition, this may be missed if you do not pay close attention.

A better approach is to describe where you have an explicit if that breaks out two possibilities. I would go further to collapse all of this into a single render call with an action argument defined 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 

This example also lacked a trap for calling find , which could throw an exception if the record was not found. This is a common occurrence, and I'm sure most people completely forget about it. Remember that in a well-designed application, even when receiving bad requests, you should not display a โ€œserver errorโ€ of 500.

The easiest way to avoid double rendering errors is to end up with only one render call.

+2
source

In the first fragment, if and return absent, and @book.special? was true, you get a DoubleRenderError . This would also cause render calls.

With this in mind, all fragments are equivalent in that they prevent the call to render twice. Also, the last snippet and return not required, since only one of render will ever be called.

+1
source

All Articles