如何在我的助手而不是视图中循环访问 ActiveRecord_Relation?

Posted

技术标签:

【中文标题】如何在我的助手而不是视图中循环访问 ActiveRecord_Relation?【英文标题】:How can I loop through an ActiveRecord_Relation in my helpers instead of views? 【发布时间】:2021-02-20 20:08:04 【问题描述】:

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

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

<% @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

我尝试了很多不同的循环方式,但每一种都返回相同的东西。

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

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

完整代码在这里:https://github.com/luisvinicius09/members-area/tree/app

【问题讨论】:

我会改用 partials,这正是它们的用途。 我同意 Eyeslandic。当你违背你应该做的事情时,它会变得更难。特别是在框架内。尤其是 Rails。 我忽略部分的唯一原因是我认为它也被视为一种视图。但下次我会接受这个建议! 【参考方案1】:

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

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

上面调用了render,但是render的返回值被忽略了,因为each不使用块的返回值。您可以使用mapjoin 的组合来收集所有渲染结果,然后将它们组合成一个字符串。

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 助手。此帮助程序对作为内容传递的不安全字符串中的特殊 HTML 字符进行转义,从而无需使用 html_escape(别名为 h)。

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

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

【讨论】:

您好,感谢您的回答。我刚刚遇到了以前的答案不起作用的情况,所以我尝试了你的并完美地工作!【参考方案2】:

查看collection rendering

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

<%= 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,它返回与@posts 相关的部分文件的默认路径。

【讨论】:

【参考方案3】:

您是否尝试过使用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

【讨论】:

以上是关于如何在我的助手而不是视图中循环访问 ActiveRecord_Relation?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Rails 视图助手提取到 gem 中?

在哪里放置不是模型、视图、控制器或助手的 Rails 代码?

视图和部分助手的示例

应用程序助手方法是不是适用于所有视图?

将值从视图传递给助手

如何通过任意 erb 文件访问任意视图助手的方法?