【问题标题】:Rails: Passing local variables from Controller to ViewRails:将局部变量从控制器传递到视图
【发布时间】:2020-10-28 14:35:08
【问题描述】:

我试图将局部变量从控制器传递到视图:

# pages_controller.rb
def my_method
  render template: "pages/new_page", message: @message
end

# new_page.html.erb
<% if message %>
  Do something
<% else %>
  Do something else
<% end %>

但这给了我未定义的局部变量或方法message 错误,而这在部分情况下可以正常工作。

我知道可以这样解决:

def my_method
  render template: "pages/new_page", locals: { message: @message }
end

我只是很想知道,在没有本地人的情况下,这是如何工作的。

【问题讨论】:

  • 本地哈希仅适用于render partial: 'pages/new_page,不适用于render template: 'pages/new_page

标签: ruby-on-rails local-variables partials actionview actioncontroller


【解决方案1】:

这都是render 的魔力(并不总是清晰或清楚记录)的一部分。根据代码中的评论 (github):

如果没有传递选项哈希或者 :update 是 指定,然后:

如果一个响应render_in的对象被传递, 在对象上调用render_in,传入当前视图 上下文。

否则,使用第二个参数渲染部分 作为本地哈希。

评论的最后一部分是相关的。当您使用render 的简写形式隐式呈现部分时,Rails 只是假设后面的散列是作为本地值传递的。所以:

<%= render 'my_partial', message: 'I hate bananas' %>

会正常工作,message 最终会在您的部分中成为本地人。

一旦你指定了一个渲染选项(讽刺的是,包括:partial),你需要显式地传递一个locals哈希来传递局部变量:

# BAD
render template: 'foo/bar', message: 'I hate bananas'
render partial: 'my_partial', message: 'I hate bananas'
render 'full_view', message: 'I hate bananas'  # no options, but not a partial

# GOOD
render template: 'foo/bar', locals: { message: 'I hate bananas' }
render 'full_view', locals: { message: 'I hate bananas' }
render partial: 'my_partial', locals: { message: 'I hate bananas' }

(我真的不讨厌香蕉。)

这部分只是意见,但我认为在一个特定用例中隐含的本地人不值得。我倾向于总是将部分本地人明确地包装为:locals 以节省记忆。另请注意,有些人会争辩说,Rails 约定是将实例变量用于完整视图而不是本地变量,但它在语法上是完全有效的。

【讨论】:

    【解决方案2】:

    您是正确的,控制器的实例变量可以在关联视图中访问。尽管您似乎没有遵循 Rails 框架。 我不确定我是否完全理解您的疑问,并会尽力一口气解释。

    # pages_controller.rb
    def home
        @message = Message.count
    end
    
    # home.html.erb
    <%= render “shared/navbar” %>
    
    <% if @message > 10 %>
        # Do something
    <% else %>
        # Do something else
    <% end %>
    
    1. Rails 指南将方法与文件名相关联。因此,“def home”将与 pages 目录中的 home.html.erb 相关联。我建议你遵循这个,因为它会变得非常混乱。
    2. 渲染部分内容通常是为视图文件夹中的“共享”目录保留的。例如,共享文件夹中的 navbar.html.erb。
    3. 最重要的是,实例变量被传递给视图。控制器中没有“@”的变量将不会发送到视图文件。

    【讨论】:

    • 在“共享”目录中通常不会使用部分。事实上,在 Rails 脚手架中实现的最常见的用途是为模型的#new 和#edit 页面使用公共表单部分。在渲染集合时也很常用。
    【解决方案3】:

    简短的回答是render是一个重载的函数,可以“短格式”调用,也就是

    render 'number_display', value: 4
    

    自动翻译成

    render :partial => 'number_display', :locals => { :value => 4 }
    

    长答案可以在here找到。

    一般来说,短格式总是会渲染部分,而第二个示例可以指定不同的选项:

    主要选项是:

    :partial - 详情请参阅ActionView::PartialRenderer[...]

    :file - 呈现一个显式的模板文件。如果需要,添加 :locals 以传入。由于缺乏验证,它不应直接用于未经处理的用户输入。

    :inline - 呈现 ERB 模板字符串。

    :plain - 呈现提供的文本并将内容类型设置为 text/plain。

    :html - 呈现提供的 HTML 安全字符串,否则首先对字符串执行 HTML 转义。设置内容类型为 text/html。

    :json - 以 JSON 格式呈现提供的散列或对象。您不需要在要渲染的对象上调用 .to_json。

    :body - 呈现提供的文本并设置 text/plain 的内容类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多