【发布时间】:2012-01-21 15:21:44
【问题描述】:
我从事 Rails 已经有一段时间了,刚刚开始深入研究 Rails 的强大功能所在的 Ruby 元编程。我真的无法弄清楚这一点,这让我发疯。 Rails 中的视图(与视图共享)如何使用控制器中的实例变量?我知道它背后有一些元编程魔法,但我无法弄清楚。在此先感谢您的帮助。
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-3 binding metaprogramming
我从事 Rails 已经有一段时间了,刚刚开始深入研究 Rails 的强大功能所在的 Ruby 元编程。我真的无法弄清楚这一点,这让我发疯。 Rails 中的视图(与视图共享)如何使用控制器中的实例变量?我知道它背后有一些元编程魔法,但我无法弄清楚。在此先感谢您的帮助。
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-3 binding metaprogramming
我现在把它留在下面是为了证明我错了。经过足够多的反对后,我决定研究一下这实际上是如何工作的。我最初的答案是在我对 Rails 非常陌生之后编写的,并且是基于我使用过的其他 MVC 库的工作方式(特别是:CodeIgniter)的假设。
AbstractController(其中ActionController::Base 包含并且您的ApplicationController 继承自)包含一个名为view_assigns 的方法。此方法从控制器的上下文中获取所有(未受保护的)实例变量,并以哈希的形式返回它们。此方法由 ActionView::Base (here) 的实例使用。
因此,基本上,实例变量是通过一些元编程魔法通过散列提供给您的视图的。您的视图绝对不会在控制器的上下文或范围内执行。这就是为什么您必须将控制器方法显式声明为辅助方法以使它们对您的视图可见。该功能由单独的元编程层启用。
它并没有那么复杂或“元”。 ActionController#render 方法在当前 ApplicationController 实例的范围内执行模板代码(erb、haml 等)。这意味着模板中的所有代码都在 ApplicationController 中的方法内执行,因此可以访问在其中执行它的对象的实例变量。
如果您不调用 render,那么 ApplicationController 将尝试根据操作名称找出使用哪个模板调用 render。
【讨论】: