Overuse of Instance Variables in Controllers?

Is there a point to assigning so many instance variables in controllers? I’ve been reading some articles about TDD and general Rails stuff and I constantly see code like this:

class Admin::ProductsController < ApplicationController
  def index
    @products = Product.order(:title)
  end
  
  def new
    @product = Product.new
  end
  
  def create
    @product = Product.new(product_params)
    
    if @product.save
      redirect_to edit_admin_product_path(@product), notice: 'The product was created successfully.'
    end
  end
  
  # ... etc
end

Instance variables in controllers, to my knowledge, are primarily for exposing content to views. So why in this example is the product being assigned to an instance variable in ProductsController#create? Is it faster to assign something as an instance variable rather than a local variable? I’m confused by this and would appreciate some insight from someone. Thanks!

In this case, it doesn’t look like the instance variable is necessary there. I try to be careful with instance variables because due to the way views work in rails, they are essentially the public interface to your controller from your views.

That said, there are some reasons you might need to have the instance variable in a create or update actions. First, if the object is invalid or fails to save, you’ll often render :new or render :edit as appropriate. These forms would require the instance variable be set.

1 Like

The way that controllers and views share instance variables is certainly one of the stranger parts of Rails. Sometimes you can end up exposing objects to the view that you didn’t intend to.

An alternate approach is to explicitly pass variables to the view by calling render, for example:

def index
  products = Product.order(:title)
  render locals: { products: products }
end
1 Like

This is the approach that lead to gems like decent_exposure being created. I like the explicitness of this example over the magic that gems add though.