Why shouldn’t I pass instance variables to views?

One of the design decisions in Rails that I thoroughly disagree with is the fact that instance variables are magically passed from the controller to the views.

For example, take this example from yesterday:

This uses a load of Rails magic. It renders app/views/documents/index.html.erb for you and sends @documents to it; presumably in index.html.erb there is a loop that iterates over the documents and renders them out individually.

There are two problems here.

Firstly, I don’t like that the render call is implicit – sometimes you redirect, sometimes you need to do an explicit render (yesterday it was because we were changing the layout) and other times you just leave it and Rails does something for you.

Secondly, we have a dependency problem. index.html.erb will fail if @documents is not set up correctly, but we can’t tell that just by looking. What if index.html.erb depends upon other variables as well?

So I would write the above like this:

I’ve added a protected method here, that separates the act of locating our documents away from the rest of the action. This just makes things a bit neater, each method does one thing and one thing only.

Then, I’ve used an explicit render call to show which template we are rendering and which variables we are passing into it. The action parameter invokes app/views/documents/index.html.erb and the locals parameter explicitly passes our documents into the view. Note, that this is as a local variable, not an instance variable, so our view looks like this:

In other words, we lose the @ from the beginning of @documents, as it’s no longer an instance variable.

It is a bit more typing, but not much.

And in the long-term, as I keep on saying, it’s important to make this stuff visible so that when you’re trying to figure out how the app works in six months time, you’re making your own life as easy as possible.

Do you know what to do but not how it works?

Ever wanted to understand why Rails views work the way that they do? Why variables from your controllers are visible inside your views?

Sign up below to get a free 5 part email course on how Ruby on Rails view rendering works and gain a deep understanding of the Rails magic.

We will send you the course, plus the occasional update from this web-site. But no spam, we promise, and it's easy to unsubscribe