Rails ERB迭代数组

时间:2015-03-15 07:26:43

标签: ruby-on-rails ruby

我试图尝试使用块以及如何在ERB中迭代集合。我有一对多关系中的模型(频道及其相应的类型)。

控制器

class HomePageController < ActionController
   def index
    @channels =  Channel.all
   end
end

然后在视图中,我迭代属于Channel的所有属性。当我想打印所有类型时,此代码为我提供了所需的输出:

视图

<% @channels.each do |channel| %>
    <% @types.each do |type| %>
        <%= Type.find(type).name %>
    <% end %>
<% end %>

起初我试图通过在一个简洁的单行中使用yield关键字来实现这一点,但我无法将任何内容打印到浏览器,只能打印到控制台

<% @types.each {|type| yield Type.find(type).name } %>

是否有等效的单行?

2 个答案:

答案 0 :(得分:3)

首先,这个方法效率很低,你正在进行n次查询,找到类型Type的每个记录,而不是通过在控制器中使用单个查询将它们转换为类型数组,假设数组在type_ids

# controller
@channels = Channel.includes(:types) # avoiding n+1 queries

# view
<% @channels.each do |channel| %>
  # some channel info output
  <% channel.types.each do |type| %>
    <%= type.name %>
  <% end %> # types loop
<% end %> # channel loop

正如@Almaron所提到的,你可以渲染一个部分以进行更简化,如果你有一个名为_type.html.erb的部分你可以直接调用渲染

# view
<%= render channel.types %>

Rails将完成所有迭代和渲染。

答案 1 :(得分:1)

首先,这种代码不属于视图。不要从视图中处理数据库(在您的情况下为Type.find())。将其移动到它所属的控制器。

要注意的第二件事是<%=<%标记之间的区别。第一个输出返回的结果,而第二个输出返回的结果。 .each的问题在于它返回了已经使用过的对象,所以在你的情况下,如果你只是<%= @types.each {|type| Type.find(type).name } %>,你就会打印出@types数组。

如果要简化该代码,可以使用辅助方法进行迭代,使用部分方法渲染每个项目。那样你会得到这样的东西 <% collection_iterate @items, 'item_partial' %>