Jerod Santo

Buy the truth, and do net sell*
📡 RSS 📥 News 🖇️ LinkedIn 🐙 GitHub 📸 Instagram 📧 Contact 🎙️ 𝕏

A Handy Method to Share Data From Rails Controllers to Views Without Requiring Direct Instance Variable Access

Rails’ method of sharing data between controllers and views via instance variables bothers many developers. For the uninitiated, a Rails controller method like this one…

class EventsController < ApplicationController
  def index
    @events = Event.scoped
  end
end

… makes the @events instance variable accessible to the rendered view.

This bugs me, too. My beefs with it are:

Better would be explicitly exposing the events collection to views via a reader and helper method, like this:

class EventsController < ApplicationController
  def index
    @events = Event.scoped
  end

  attr_reader :events
  helper_method :events
end

Now all views can just call the events method and not worry about the ivar.

This becomes cumbersome when you do it across many controllers and actions, so I use this handy method to “automate” the process to expose certain ivars to views:

class ApplicationController < ActionController::Base
  # short hand for exposing a list of ivars to view objects
  def self.exposes(*ivars)
    ivars.each do |ivar|
      attr_reader ivar.to_sym
      helper_method ivar.to_sym
    end
  end
end

The method takes an arbitrary list of ivar names. Using it, the example controller class looks like this:

class EventsController < ApplicationController
  exposes :events

  def index
    @events = Event.scoped
  end
end

Unfortunately, the view can still access @events, but it’s a step in the right direction.

I’m sure there are ways to stop direct access of instance variables from views, but I haven’t gotten that drastic yet.

I’ve gotten a lot of mileage out of this method. Perhaps you will too.