BEST_PRACTICES /
Avoiding Instance Variables in Views

← Back

In general, passing data between templates with instance variables is discouraged. This even applies from controllers to templates, not just between partials.

:locals can be used to pass data from a controller just like partials.

def show
  render "blob/show", locals: {
    :repository => current_repository,
    :commit     => current_commit,
    :blob       => current_blob
  }
end

Or if you're using a view model, a local view will be passed to the template.

def show
  render_template_view("blob/show", Blob::ShowView,
    :repository => current_repository,
    :commit     => current_commit,
    :blob       => current_blob
  )
end

Rails implicit renders are also discouraged.

Always explicitly render template with a full directory path. This makes template callers easier to trace. You can find all the callers of "app/view/site/hompage.html.erb" with a simple project search for "site/homepage".

def homepage
  render "site/homepage"
end

Exceptions

There are some known edge cases where you might be forced to use instance variables. In these cases, its okay to add <%# rubocop:disable Lint/InstanceVariable %> to your view.

Legacy templates

If you need to call a subview that expects an instance variable be set. If possible consider refactoring the subview to accept a local instead.

Layouts

Unfortunately the only way to get data into a layout template is with instance variables. You can't explicitly pass locals to them.