Rails 3,将局部变量传递给局部视图

26

可能重复:
Rails:对传递局部变量给partials的语法感到困惑

我想将局部变量(模型中没有相关字段)传递给partial。

# infos/index.html.erb

<%= render :partial => 'info', :locals => {:info => first, :img_style => "original"} %> 

:img_style将是图像的html样式。

# infos/_info.html.erb
<% first = @infos.shift %>
<%= image_tag(info.image.url, :class => img_style),  info %> 
# and here goes code for normal iteration
<% @infos.each do |e| %>
# etc

但是它不起作用,返回错误:

# GET /infos/
undefined local variable or method `img_style' for #<#<Class:0xc471f34>:0xc470cc4>

能否不制作冗余的部分来完成?

抱歉我的英语不好。:P

编辑:

模型信息没有:img_style字段。

# db/schema.rb
  create_table "infos", :force => true do |t|
    t.string   "title"
    t.text     "description"
    t.integer  "place_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
    t.text     "short"
  end

编辑2:

即使简单

<%= img_style %>

don't works.

Application Stack Trace

app/views/infos/_info.html.erb:3:in `_app_views_infos__info_html_erb___1029249744_92158380_1472718'
app/views/infos/index.html.erb:7:in `_app_views_infos_index_html_erb__184644561_92172050_0'
app/controllers/infos_controller.rb:8:in `index'

编辑3:

视图

# infos/index.html.erb
<div >
  <h1><%= t('info.infos') %></h1>
  <div id="left">
    <% first = @infos.shift %>
    <div>
      <% @aimg_style = "original"%>
      <%= render 'info', :locals => {@img_style => @aimg_style } %>
    </div>
    <ul>
      <% @infos.each do |e| %>
        <li>
          <div>
            <%= render :partial => 'info', :object => e %>
          </div>
        </li>
      <% end %>
    </ul>
    <%= will_paginate @infos %>

# infos/_info.html.erb
<%#= link_to thumbnail(info, "listTabsImg", false, img_style), info %>
  <%#= image_tag(info.image.url()) %>
  <%= img_style %>
<p>
  <strong class="nameBox"><%= link_to info.title, info %></strong>
  <span><%= info.short %>...</span>
  <%= link_to "#{t('more')} »", info %>
</p>

终于

这不起作用:

# infos/index.html.erb
<% first = @infos.shift %>
<div class="boxEvent">
  <% @aimg_style = "original"%>
  <%= first %>
  <%= render 'info', :locals => {:info => first, :img_style => @aimg_style } %>
</div>

这个有效:

# infos/index.html.erb
  <% @infos.each do |e| %>
    <li>
      <div class="boxEvent">
        <%= render :partial => 'info', :locals => {:info => e, :img_style => "original"} %>
      </div>
    </li>
  <% end %>

有人知道为什么吗?


哪一行代码在哪个文件中?<%= image_tag是否放置在_info局部文件中,还是其他地方?当局部文件被你的第一个示例调用时,错误是否会引发,还是你从其他地方调用它?我问这个问题是因为你提到了冗余的局部文件,但你没有说过你是否从多个地方调用该局部文件。 - Arsen7
这可能算不上什么——因为你的问题已经包含了正确的代码——但使用简写语法会导致失败:render 'info',:locals => { ... }。如果你是显式调用局部视图,render :partial => 'info',:locals => { ... },那么我看不出任何原因导致它不工作。如@Arsen7所建议的那样,了解你的模板嵌套局部视图的方式将会很有帮助。 - neezer
@Arsen7 当我从浏览器中获取/infos时,会出现错误。我想做到没有冗余的部分(例如:_info_small.html.erb、_info_original.html.erb等每个样式一个部分)。 - nothing-special-here
你的模型不需要一个img_style字段。当你调用partial时,你正在定义它。 - Devin M
如果现在的问题是“为什么?”,那我会说这是Rails中的一个bug。但通常在编程中,尽可能具体是很好的。猜测和魔法通常会导致沮丧。如果我想呈现一个partial,那么我应该明确地说明。在这种情况下,遵守这个规则会意外地拯救你 ;) - Arsen7
回答为什么它会像那样工作:https://dev59.com/s2855IYBdhLWcg3wViu3 - nothing-special-here
5个回答

50

实际上,我只是在Rails 3中使用这个语法:

render "a_partial", :a_local_variable => whatever, :another_variable => another

7
嗯...这个语法也不起作用:undefined local variable or method 'img_style' for #<#<Class:0xb477984>:0xb474978> - nothing-special-here
1
它应该可以正常工作。变量必须从其他范围内被访问。 - d11wtq
如果这对你仍然不起作用 - 可能是你的部分被缓存了。为了检查这一点,在你的部分开头添加任何垃圾(例如一行“lalala”),并检查这次值是否传递到了部分。 - Alexander

12

这个应该可以工作:

<%= render :partial => "info", :locals => { :img_style => "original" } %>

使用这个部分:

# infos/_info.html.erb
<%= image_tag(info.image.url, :class => img_style),  info %>

不过,如果调用了错误的局部变量,请尝试将以下内容用作局部变量:

# infos/_info.html.erb
<%= image_tag(info.image.url(img_style)),  info %>

5

我在这个问题上花了几个小时;在一个视图中,如果你首先调用:

render :partial => ? , :locals => (....}

render :partial => ? without a locals hash

然后调用:partial => ? 并使用一个本地哈希表进行渲染,但该本地哈希表并不会传递给视图。

如果第一次调用包含一个本地哈希表,并将相同的变量设置为'',那么第二次调用使用真实值就会起作用。


3
这不是一个错误,而是一种功能。 :) - nothing-special-here
听起来你是在说第一次调用render可能会破坏后续的调用。我从未遇到过这种情况。你能详细说明或澄清一下吗?谢谢。 - Nathan
这确实是一个非常简单的“功能”。如果你有一个要求foopartial,那么在调用render partial时不传递foo的值将导致未定义变量错误。所以代码中断的地方不是你传递变量的地方,而是你没有传递它的地方。顺便说一下,如果你真的想要一个“可选”的局部变量,在partial中用defined?来保护它,就像这样:foo if defined? foo - Leonid Shevtsov

2

你的代码(第一行所示的那个)应该可以工作。没有错误。我甚至自己测试了一下,对我来说也可以工作。

出现这种错误的常见原因是:

  • 变量名拼写错误
  • 从其他地方调用部分文件,在那里你没有传递一个 :local 参数。

你的模型没有属性 "img_style" 也不重要。

我可以看到在你的 infos/index.html.erb 中,你有两个地方调用了 render :partial => 'info', :object => ... 而你在这里没有使用 :locals。只是行号与之前发布的 stacktrace 不匹配,所以很难说哪个调用会导致问题。

我猜测渲染方法的两个调用都需要更正。

在第一个调用中,要具体一些,调用 render :partial => "info" 而不是 render "info"。这可能是Rails中的一个漏洞,但由于某种奇怪的原因,在这种情况下 :locals 似乎没有传递到视图中。

在第二个调用中,只需添加 :locals。


1

我认为问题在于结尾的, info调用。它正在info对象中查找img_style。你不需要它。

我喜欢使用partials,但最近也发现了helper方法的美妙之处,特别是在像这样简单的渲染中。

def info_image(info, class_name="original")
   image_tag(info.image.url, :class => class_name)
end

然后就是

<%= info_image(first) %>

或者

<%= info_image(first, "anotherclass") %>

在视图中。更加简洁。

如果变得更复杂。你只需要在一个地方修改代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接