Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are instance variables in controllers made available to views in Rails

I have been doing Rails for a while now and just started to dive deep into Ruby meta-programming which Rails gets its power from. I really couldn't figure this one out and it is making me crazy. How are instance variables in controllers made available to views(shared with views) in Rails? I know there is some meta-programming magic behind it, but I couldn't figure it out.Thanks in advance for all your help.

like image 928
Sait Mesutcan Ilhaner Avatar asked Dec 16 '11 00:12

Sait Mesutcan Ilhaner


1 Answers

Update: Original accepted answer was wrong

I'm leaving it below for now to demonstrate how wrong I was. After enough downvotes I have decided to look into how this actually works. My original answer was written after I was very new to rails and was an assumption based on how other MVC libraries I had used worked (specifically: CodeIgniter).

How it actually works (as of Rails 4)

AbstractController (which ActionController::Base includes and your ApplicationController inherits from) includes a method called view_assigns. This method grabs all the (non-protected) instance variables from the context of your controller and returns them in a hash. This method is consumed by instances of ActionView::Base (here).

So, basically, instance variables are provided to your view by a hash through a bit of meta-programming magic. Your view is definitely not executed in the context or scope of your controller. This is why you must explicitly declare controller methods as helper methods to make them visible to your views. That feature is enabled by separate layer of meta programming.

Original (wrong) answer:

It's not really that complicated or "meta". The ActionController#render method executes the template code (erb, haml, whatever) within the scope of the current ApplicationController instance. That means that all of the code within your template is executed inside of a method within your ApplicationController, and as such has access to the instances variables of the object it was executed inside of.

If you don't call render then ApplicationController will try to figure out which template to call render with based on the action name.

like image 146
Carl Zulauf Avatar answered Sep 28 '22 09:09

Carl Zulauf