如何将Rails实例变量传递给视图?

sup*_*ary 49 ruby-on-rails

在我的Rails应用程序中,我有一个这样的控制器:

class MyController < ApplicationController
  def show
    @blog_post = BlogPost.find params[:id]
  end
end
Run Code Online (Sandbox Code Playgroud)

在我看来,我可以这样做:

<%= @blog_post.title %>
Run Code Online (Sandbox Code Playgroud)

我对魔法感到不舒服.这是如何实现的?

mec*_*ish 81

在呈现视图时,从控制器中拾取实例变量及其值,并将其传递给视图初始化程序,后者将它们设置为视图实例.这是使用这些ruby方法完成的:

instance_variables- 获取实例变量的名称(文档) instance_variable_get(variable_name)- 获取实例变量的值(文档) instance_variable_set(variable_name, variable_value)- 设置实例变量的值(文档)

这是Rails代码:

收集控制器实例变量(github):

def view_assigns
  hash = {}
  variables  = instance_variables
  variables -= protected_instance_variables
  variables -= DEFAULT_PROTECTED_INSTANCE_VARIABLES
  variables.each { |name| hash[name[1..-1]] = instance_variable_get(name) }
  hash
end
Run Code Online (Sandbox Code Playgroud)

将它们传递给视图(github):

def view_context
  view_context_class.new(view_renderer, view_assigns, self)
end
Run Code Online (Sandbox Code Playgroud)

在视图中设置它们(github):

def assign(new_assigns) # :nodoc:
  @_assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) }
end
Run Code Online (Sandbox Code Playgroud)

  • 还可以通过rails git repo链接增强你的答案吗? (6认同)
  • Mechanicalfish 解释了它的工作原理,因此很明显这背后并没有什么“魔法”;然而我也对这种机制感到不舒服,因为我认为它破坏了封装,并且我找到了一个以非常干净的方式解决这个问题的宝石:https://github.com/voxdolo/decent_exposure (2认同)