Rails使用多个对象呈现部分视图

8
这段代码运行正常:
<%= render 'sidebars/pages', :object => @categories = pages , :object => { @myobject => '1', @mmyobject => '2' } %>

如果我改成这样:

<%= render 'sidebars/pages', :object => { @categories => pages, @myobject => '1', @mmyobject => '2' } %>

然后当partial尝试迭代@categories时,我收到了一个错误。
undefined method `each' for nil:NilClass

我对Ruby和Rails都非常陌生,非常感谢任何帮助。

谢谢!

2个回答

15
当你将 :object 传递给 Rails 的一个局部视图时,该视图内部定义了一个与该局部视图同名的局部变量(而不是以@ 开头的实例变量)。所以对于局部视图 sidebars/_pages.html.erb,你的局部变量将被称为 pagespages 局部变量的值是作为 :object 选项值传递的哈希表,而在“外部”视图中拥有的任何实例变量(比如 @categories@myobject)都不可用。因此,你需要通过 pages 局部变量来访问这些变量。
你可能正在寻找以下内容:
<%= render 'sidebars/pages', :object => { :categories => @categories, :myobject => '1', :mmyobject => '2' } %>

sidebars/_pages.html.erb 中,你可能会有类似以下的内容:

<p><%= pages[:myobject] %></p>

<ul>
<% pages[:categories].each do |category| %>
  <li><%= category %></li>
<% end %>
</ul>

详见Rails Guide to Layouts and Rendering的Partials章节,了解更多细节。

更新:

使用:locals选项会是一个更好的解决方案,它接受一个Hash作为参数,并将其键变成partial中的局部变量。例如:

<%= render 'sidebars/pages', :locals => { :categories => @categories, :myobject => '1', :mmyobject => '2' } %>

sidebars/_pages.html.erb中,你可能会有类似这样的内容:
<p><%= myobject %></p>
<p><%= mmyobject %></p>

<ul>
<% categories.each do |category| %>
  <li><%= category %></li>
<% end %>
</ul>

谢谢您的快速回复,Stuart先生。pages是一个辅助方法,它只返回Category.all。我在partials中使用@categories.each do |c|。我知道最好使用局部变量而不是实例变量的最佳实践,我只是好奇为什么我的第二行代码不起作用。 - user2094178
我不确定,但是你的第二行代码可能无法正常工作,因为你的 Hash 设置了 @categories => pages。你可能不想让哈希键成为 @categories,因为你不会通过那个键来访问它。它应该是像 :categories => pages 这样的东西。 - Stuart M
Stuart 先生,我再次检查了我的第一行代码,发现 @myobject@mmyobject 没有被传递到视图中,由于没有引发任何错误,我认为这是可以的。对于我的疏忽我深感抱歉。 - user2094178

1

如上所述,此行代码为:

<%= render 'sidebars/pages', :object => @categories = pages , :object => { @myobject => '1', @mmyobject => '2' } %

实际上并没有出现任何错误,但也没有将@myobject和@mmyobject传递给视图。
以下是使用render方法指定多个对象的正确*方法:
<%= render 'sidebars/pages', :object => [@categories = pages, @myobject = '2'] %>

这样我就可以将多个对象传递给视图,而无需定义超过一次的 :object。

*至少在我的知识范围内是如此


我认为你可能误解了 @categories = pages 的作用:它将实例变量 @categories 设置为 pages。在 render 语句中进行该赋值并不是语法上的无效,但它没有什么实际意义。例如,这并不意味着你可以在局部模板中访问 @categories - Stuart M
我认为你最好使用:locals选项而不是:object。你可以这样说render 'sidebars/pages',:locals => {:categories => @categories, :myobject => '2'},然后你就可以在局部中访问名为categoriesmyobject的本地变量。请参阅Rails指南中的“传递本地变量”部分。 - Stuart M
是的,我明白先生。我只是试图弄清楚如何使实例变量对来自视图的部分可用,因为<%= render 'sidebars/pages' %>位于视图中,到目前为止我只知道从视图传递多个本地变量或一个对象到部分。通过上面的示例,我在部分中有可用的@categories,这次我进行了双重检查。页面方法来自测试目的的帮助程序,并且与Category.all相同。我正在使用Rails 4进行测试。 - user2094178
我正在使用@categories = pages,因为我不希望它在控制器中,如果我使用before_filter在ApplicationController中将其可用,那么即使未使用它也会被请求。 - user2094178

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