我怎样才能在我的助手而不是视图中循环遍历 ActiveRecord_Relation?

How can I loop through an ActiveRecord_Relation in my helpers instead of views?

我正在尝试从我的视图中移出一个循环语句,该循环语句迭代 ActiveRecord_Relation 中的每个元素并将其放在我的助手身上。

这是我在视图中用于为数据库中的每个 post 生成卡片的代码:

<% @posts.each do |post|%>
  <div class="post-container">
    <div>
      <h2 class="m-0-p-0"><%= post.title %></h2><br/>
      <hr class="m-0-p-0" />
      <%= second_useless_helper(user_signed_in?, post) %>
    </div>
    <div>
      <h4><%= post.body %></h4>
    </div>
  </div>
<% end %>

但是当我尝试使用此代码遍历我的助手时:

def useless_loop
  @posts.each do |item|
    render inline: '<p>' + item.title + '</p>'.html_safe
  end
end

这是我得到的: Code returned from the loop in helpers

我尝试了很多不同的循环方式,但每一个 returns 都是一样的。

我唯一能做的就是通过括号表示法访问每个项目的值 (例如:@posts[0].title 或@posts[4].body)。但是当我试图循环它时我失败了。

我搜索了很多关于正在发生的事情以及循环不起作用的原因,但我无法弄清楚。

完整代码可在此处获得:https://github.com/luisvinicius09/members-area/tree/app

您尝试过使用 Builder::XMLMarkup 吗? (reference) 类似于:

def useless_loop
  html = Builder::XmlMarkup.new(:indent => 2)

  @posts.each do |post|
    html.div {
      html.div {
        html.h2(post.title)
      }
    
      html.div {
        html.h4(post.body)
      }
    }
  end

  return (html).html_safe
end

查看 collection rendering

如果你使用了partials,你可以用这一行替换所有的循环代码:

<%= render @posts %>

然后创建一个新的 views/posts/_post.html.erb 文件:

  <div class="post-container">
    <div>
      <h2 class="m-0-p-0"><%= post.title %></h2><br/>
      <hr class="m-0-p-0" />
      <%= second_useless_helper(user_signed_in?, post) %>
    </div>
    <div>
      <h4><%= post.body %></h4>
    </div>
  </div>

说明:当您调用 render @posts 时,Rails 将尝试找出要渲染的部分,并将调用 @posts.to_partial_path 哪个 return 部分的默认路径与 @posts.

相关的文件

您的 useless_loop 助手工作正常。 return 是帖子集合的原因是因为 Array#each return 是 self.

def useless_loop
  @posts.each do |item|
    render inline: '<p>' + item.title + '</p>'.html_safe
  end
end

在上面进行了 render 调用,但是 render 的 return 值被忽略,因为 each 不使用 return 值一个块。您可以使用 map and join 的组合来收集所有渲染结果,然后将它们连接成一个字符串。

def useless_loop
  @posts
    .map { |item| render inline: "<p>#{h item.title}</p>".html_safe }
    .join
    .html_safe
end

然而根本不需要 render 调用。

.map { |item| render inline: "<p>#{h item.title}</p>".html_safe }
# can be replaced with
.map { |item| "<p>#{h item.title}</p>".html_safe }

您也可以使用 tag helper. This helper escapes special HTML characters in unsafe strings passed as content, which removes the need to use html_escape(别名为 h)。

def useless_loop
  @posts.map { |item| tag.p(item.title) }.join.html_safe
end

我不确定是否需要最后的 .html_safe 调用。如果数组中的所有元素都标记为 HTML 安全,则生成的字符串可能会自动标记为 HTML 安全。我目前手头没有 Rails 环境,因此您必须自己测试一下。