Controller to View Data Hand-off in Rails

I’m reading the classic Rails 7 Way by Obie Fernandez (fantastic read, highly recommended, btw) and would like some clarification regarding Rails controller and views.

We know that the instance variables of a controller are shared with the views.

In the chapter on Rails controllers, the book mentions:

There’s a bit of irony (and possible confusion for newcomers) in the choice of instance variables to share data between controllers and views…

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.

My question is: is Rails still looping through the instance variables and copying them one by one? Or has the underlying implementation been updated since the first edition of this book was written (which was quite a long time ago) that do this hand-off more efficiently?

To be clear, I’m not talking about the hand-off approach (with instance vars being directly available in the views - I love it), just its underlying implementation.

I can (and will) dig into the source code to see how it’s done, but would love to get more information here from the Rails experts, that might not be evident from the source.

Thanks!

1 Like

Kind of a two part process here … first part comes in AbstractController::Rendering#view_assigns where Rails goes through all instance variables in the controller and copies just pointers into a new hash object. It skips all of these:

Protected controller instance variables
@_action_name
@_response_body
@_formats
@_prefixes
@_params
@_response
@_request
@_config
@_url_options
@_action_has_layout
@_view_context_class
@_view_renderer
@_lookup_context
@_routes
@_view_runtime
@_db_runtime
@_helper_proxy

Second this hash of variable name / value pairs is processed as a last step when a new ActionView::Base object is instantiated. The generated hash gets passed into ActionView::Base#assign, which iterates through the hash and sets the instance variables on that new view object.

2 Likes

Thanks @Lorin_Thwaits, that was very helpful.