我试图尝试使用块以及如何在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 } %>
是否有等效的单行?
答案 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' %>