Double

The more I experiment with other technologies, the more I realize what a joy it is to work with Rails and Ruby every single day.

I take for granted the baked-in convention-over-configuration ethos, which allows developers to maximize their efforts with genuine building and creativity.

Take for example the following:

Implicit rendering

When spinning up a new action in ActionController, you do not need to specify what template to render. As long as the namespaces match and are found in app/views, your application will do the work for you. If you stay RESTful on a CRUD app you may rarely if ever find yourself manually rendering templates.

def index
@books = Book.all
end
#=> Rendering books/index.html.haml within layouts/application

See? It knows to spit out the associated view. This is the kind of joy you experience from day one with the framework.

Explicit rendering

There will be times when we stray as we continue building larger applications. That’s okay though! Rails is convention over configuration, not the banishment of configuration altogether. In that case we can send the template explicitly down….

def show
@book = Book.find(params[:id])
render 'unexpected'
end
#=> Rendering books/unexpected.html.haml within layouts/application

… and Rails knows what we’re about.

Extra curricular activity

That doesn’t mean we can’t overlook something big. It’s important to note the easily-missed case where we can be executing unexpected code. Take the following example:

def extra_curricular_activity
@book = Book.find(params[:id])
render 'show'
@book.update_column(:title, 'Surprise Surprise')
end
#=> SQL (7.1ms) UPDATE "books" SET "title" = 'Surprise Surprise' WHERE "books"."id" = $1 [["id", 1]]

It may be obvious from such a small controller action, but this can easily be missed as controllers get more fat. All code after a redirect or render is still executed. That means in this case we see this page:

Double

But if we refresh we notice that our title indeed was updated behind the scenes.

Double

While building out controllers and especially as they get larger, be sure to take care to consider code that may be executed after.

Handling DoubleRenderError

Worth remembering is that render or redirect code is executed more than once. See below:

def double_render_error
@books = Book.all
render 'index'
render 'show'
end
#=> AbstractController::DoubleRenderError - Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action.

You’ve probably encountered this error a fair few times yourself. Most likely as controllers are growing. If you find yourself unable to remove the render or redirect (which I recommend trying first) you can resolve this by calling and return after the render is hit.

def blocks_double_render_error
@books = Book.all
render 'index' and return
render 'show'
@books.last.update_column(:title, 'Or am I?')
end
#=> Rendering books/index.html.haml within layouts/application
#=> Book.last.title
#=> "Surprise Surprise"

This also precludes all later code from executing, which is a handy tool in the event that you not only want to prevent a DoubleRenderError, but stop later code from executing.

When we visit '/books/blocks_double_render_error' we can clearly see that the code has not executed on the title attribute.

Double

Conclusion

If you want to have a play with this yourself, I fired up a repo with the example code that you can access.

For a deeper dive on this, I heartily recommend The Rails 5 Way by Obie Fernandez. It is my absolute favorite Rails 5 reference to date.

Stay in Touch

I like to write about Ruby and building things, typically once every month or so. Get an email when I have written something new.