Quoting Obie Fernandez from The Rails 3 way:
The way Rails implements controller-to-view data handoffs is through
instance variables. Typically, a controller action initializes one or
more instance variables. Those instance variables can then be used by
the view.
There’s a bit of irony (and possible confusion for
newcomers) in the choice of instance variables to share data between
controllers and views. The main reason that instance variables exist
is so that objects (whether Controller objects, String objects, and so
on) can hold on to data that they don’t share with other objects. When
your controller action is executed, everything is happening in the
context of a controller object—an instance of, say, DemoController or
EventController. Context includes the fact that every instance
variable in the code belongs to the controller instance.
When the view template is rendered,
the context is that of a different object, an instance of
ActionView::Base. That instance has its own instance variables, and
does not have access to those of the controller object.
So instance
variables, on the face of it, are about the worst choice for a way for
two objects to share data. However, it’s possible to make it happen—or
make it appear to happen. What Rails does is to loop through the
controller object’s variables and, for each one, create an instance
variable for the view object, with the same name and containing the
same data.
It’s kind of labor-intensive, for the framework: It’s like
copying over a grocery list by hand. But the end result is that things
are easier for you, the programmer. If you’re a Ruby purist, you might
wince a little bit at the thought of instance variables serving to
connect objects, rather than separate them. On the other hand, being a
Ruby purist should also include understanding the fact that you can do
lots of different things in Ruby—such as copying instance variables in
a loop. So there’s nothing really un-Ruby-like about it. And it does
provide a seamless connection, from the programmer’s perspective,
between a controller and the template it’s rendering.