what controller data is accessible in html.erb?

被刻印的时光 ゝ 提交于 2021-01-28 18:58:41

问题


I'm trying to understand how the controller class and the .html.erb view files in Rails are connected, and how the view accesses data in the controller methods. For example, I have the following controller class:

class SomeController < ApplicationController 

   def show
     # defining some data to access in the view
     x = 1
     @y = 2
   end

end

If in the corresponding .html.erb view file, I try to access @y, this works fine

<p> <%= @y %> </p>

However, if I try to access x, it gives an error

<p> <%= x %> </p>

undefined local variable or method 'x'

Conceptually, why @y is accessible in the .html.erb view, but x is not.

PS: I should add that I know variables with @ indicate instance variables in Ruby, so (I think) @y would be an instance variable of the instance of SomeController. However, I'm unclear how this affects what .html.erb view file has access to from SomeController.


回答1:


As per the description and the answers mentioned above it is clear that instance variables are accessible in the views.

Answering the below mentioned point

Conceptually, why @y is accessible in the .html.erb view, but x is not.

While rendering the views, instance variables and their values are taken from the controller and passed to the view initializer which assigns them to the view instance.

This is done using these ruby methods:

instance_variables - gets names of instance variables  
instance_variable_get(variable_name) - gets value of an instance variable 
instance_variable_set(variable_name, variable_value) - sets value of an instance variable 

[https://github.com/rails/rails/blob/0c5552a3dd28e35cce64462765cc41c5355db0f1/actionpack/lib/abstract_controller/rendering.rb#L138-L145][1]

In the above link the method named

"view_assigns" -> collects the controller instance variable
"view_context passes" -> them to the views
"assign(new_assigns)" -> setting them in the view



回答2:


In RoR if you declare a variable in your controller as an instance variable @y it becomes available to your view. On the other hand x is the local variable and is only accessible within it's scope.




回答3:


As per your example, @y in the controller is not the same @y in the view, however at the very high level it seems like they're the same. Rails does a lot of magic under the hood, As you already know (if not), Rails believes in Convention over configuration, at this point Rails will look for all the instance variables in the controller and will copy them over to the views, even let's say you don't want them, it'll be there. Rails is exposing all the instance variables to the respective view. So far, this has been my understanding, if I have missed something, please add more details.




回答4:


About variables:

  • foo = 'bar' # this means that you declare a local variable, not accessible from view

  • @foo = 'bar' # means you declare an instance_variable, this will be available on view

Also you can define helper_method on controller that execute and returns some data, like helpers.




回答5:


This is a matter of scope (scope defines where in a program a variable is accessible). Ruby has four types of variable scope, local, global, instance and class.

In your case:

  • x is a local variable, they are local to the code(method, loop etc.) in which they are declared.
  • @y is an instance variable, they are visible anywhere in the instance of the class in which it has been defined.

You can access x if you explicitly provide it as local:

def show
   render locals: {
      x:  1
   }
end

The recommended way to use variables in views is to use instance variables. That's because if you try to use a local variable and you didn’t pass a value in, you would get an error. But with instance variables, you would get a nil.

For more information on how to use local variables in a view, you can check the link.



来源:https://stackoverflow.com/questions/52100888/what-controller-data-is-accessible-in-html-erb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!