Exposure of Variables
Learn and discuss the exposure of variables in Rails application.
We'll cover the following
Expose one instance variable per action
The way Rails makes data from controllers available to views is by copying the instance variables of the controller into the code for the view as instance variables with the same name. We highly suggest being ok with this design. We’ll talk about object orientation and controllers more in the chapter on controllers, but we don’t think there is high value in circumventing this mechanism with something that feels cleaner or more object-oriented.
That said, it’s possible to create quite a mess with instance variables, so that’s what we want to talk about here. The way to get the most of Rails’ design without creating a problem is to adopt two conventions:
- Expose exactly one instance variable from any given action, ideally named for the resource or resources being manipulated by the route to that action. For example, the widget show page should only expose
@widget
. - There are exceptions: when a view requires access to reference data, like a list of country codes, when the view needs access to global context, like the currently logged-in user, or when there is UI state that is persisted across page refreshes, such as the currently selected tab in a tab navigation control.
These conventions are surprisingly easy to follow, but it does require doing a good job modelling your domain and resources. The key situation to avoid is exposing multiple instance variables that collectively represent the resource rather than creating a single instance variable and perhaps a new model class to do so.
Name the instance variable after the resource
As a reminder, our suggestion is to create routes based on resources that use the Rails conventional actions. This results in an application with many resources. Each controller would then expose a single instance variable named for that resource (for example, @widget
or @widgets
).
The primary prerequisite of this guideline is that your resources be well designed. Whatever information is needed to render a given view, the resource for that view must have access to all of it. How we do this is a design decision with many subtleties, particularly around the so-called Law of Demeter, which warns against coupling domain concepts too tightly. Most developers interpret the Law of Demeter as avoiding nested method calls like the following:
@widget.manufacturer.address.country
We would not have a huge problem with the Guideline of Demeter, but as a Law, we find it over-reaches, especially given how it is often interpreted. In many cases, it’s perfectly fine—and often better—to dig into the object hierarchy for the data we need.
Let’s add some code to our widget show page to see the exact problem created by the single instance variable approach and the Law of Demeter. For this example, we’ll assume our domain model in the figure below describes our domain, which is:
- A widget always has a manufacturer.
- A manufacturer can manufacture many widgets.
- A manufacturer always has an address.
- An address is always a country.
Get hands-on with 1400+ tech skills courses.