【问题标题】:what controller data is accessible in html.erb?在 html.erb 中可以访问哪些控制器数据?
【发布时间】:2019-02-05 15:02:17
【问题描述】:

我试图了解控制器类和 Rails 中的 .html.erb 视图文件是如何连接的,以及视图如何访问控制器方法中的数据。例如,我有以下控制器类:

class SomeController < ApplicationController 

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

end

如果在相应的.html.erb视图文件中,我尝试访问@y,这样就可以了

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

但是,如果我尝试访问 x,则会出现错误

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

未定义的局部变量或方法'x'

从概念上讲,为什么 @y 可以在 .html.erb 视图中访问,而 x 却不能。

PS:我应该补充一点,我知道带有 @ 的变量表示 Ruby 中的实例变量,所以(我认为)@y 将是 SomeController 实例的实例变量。但是,我不清楚这会如何影响 .html.erb 视图文件可以从 SomeController 访问的内容。

【问题讨论】:

  • 你需要了解local variablesinstance variables
  • 我明白了,所以局部变量只在方法内有作用域,而视图文件可以访问控制器实例。有道理!
  • A local variable 仅在当前 context 中具有范围,这意味着如果您将其定义为 inside 一个方法,则该方法的 outside 无法访问它,但是 instance variable 具有整个范围class 的一个实例,它们可用于在同一 instance 上调用的任何方法中。

标签: ruby-on-rails model-view-controller erb


【解决方案1】:

在 RoR 中,如果您将控制器中的变量声明为实例变量 @y,则它对您的视图可用。 另一方面,x 是局部变量,只能在其范围内访问。

【讨论】:

  • 但是,如果您明确将其作为本地提供,您可以访问 xrender :show, locals: {x: x}
【解决方案2】:

这是一个范围问题(范围定义了程序中变量可访问的位置)。 Ruby 有四种类型的变量作用域,localglobalinstanceclass

在你的情况下:

  • x 是一个局部变量,它们是声明它们的代码(方法、循环等)的局部变量。
  • @y 是一个实例变量,它们在定义它的类的实例中的任何位置都可见。

如果您明确将x 提供为本地,则可以访问它:

def show
   render locals: {
      x:  1
   }
end

在视图中使用变量的推荐方法是使用instance variables。那是因为如果你尝试使用 local variable 并且你没有传递一个值,你会得到一个错误。但是使用instance variables,您将获得nil

有关如何在视图中使用local variables 的更多信息,您可以查看link

【讨论】:

    【解决方案3】:

    根据上面提到的描述和答案,很明显实例变量可以在视图中访问。

    回答下面提到的一点

    从概念上讲,为什么 @y 可以在 .html.erb 视图中访问,但 x 是 不是。

    在渲染视图时,实例变量及其值从控制器中获取并传递给视图初始化器,后者将它们分配给视图实例。

    这是使用这些 ruby​​ 方法完成的:

    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]

    在上面的链接中,方法名为

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

    【讨论】:

      【解决方案4】:

      根据您的示例,控制器中的@y 与视图中的@y 不同,但是在非常高的级别上,它们似乎是相同的。 Rails 在后台做了很多神奇的事情,如您所知(如果不是),Rails 相信约定优于配置,此时 Rails 将在 @ 中查找所有 instance variables 987654325@ 并将它们复制到views,即使你不想要它们,它也会在那里。 Rails 将所有实例变量暴露给各自的视图。 到目前为止,这是我的理解,如果我遗漏了什么,请补充更多细节。

      【讨论】:

        【解决方案5】:

        关于变量:

        • foo = 'bar' # 这意味着你声明了一个局部变量,不能从视图中访问

        • @foo = 'bar' # 表示你声明了一个instance_variable,这将在视图中可用

        您还可以在执行并返回一些数据的控制器上定义helper_method,例如helpers

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-03
          • 2021-10-28
          • 1970-01-01
          • 1970-01-01
          • 2011-09-07
          • 2016-08-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多