You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ERB中遍历Rails的has_many :through关联且不产生重复内容

问题原因
  • 核心原因是has_many :through关联默认不会自动去重:你当前Section和同一个Category之间有N条Post关联记录,调用s.categories时就会返回N个完全相同的Category对象,遍历的时候自然会重复输出N次,重复次数和Post数量完全对应。
  • 次要问题是控制器逻辑不符合Rails规范:Section详情页不需要查询全量Section.all再在视图层判断路径匹配,属于不必要的冗余逻辑,也会带来额外的性能开销。
解决方案

第一步:修复关联定义自动去重

修改Section模型中的categories关联,添加去重约束:

class Section < ApplicationRecord
  has_many :posts
  # 加 -> { distinct } 让关联查询自动去重
  has_many :categories, -> { distinct }, through: :posts
   
  has_rich_text :description

  def to_param
    url
  end
end

修改后调用@section.categories只会返回不重复的分类对象,直接解决重复输出问题。

第二步:优化控制器逻辑(符合Rails规范)

Section详情页对应的控制器方法(一般是sections_controller.rb的show方法)直接查询单个Section对象即可,不需要查全量数据:

class SectionsController < ApplicationController
  def show
    # 因为你重写了to_param用url字段作为路由参数,所以用url查询
    @section = Section.find_by!(url: params[:id])
  end
end

第三步:简化视图代码

去掉冗余的全量Section遍历和路径判断逻辑,直接使用控制器查询到的单个@section对象:

<% @section.categories.each do |c| %>
  <h1><%= c.title %></h1>
  <p><%= c.description %></p>
  <% # 只取当前Section下属于该分类的Post,避免拿到其他Section的同分类Post %>
  <% c.posts.where(section: @section).each do |p| %>
    <%= p.title %>
  <% end %>
<% end %>
补充说明

如果你不想修改关联定义,也可以在视图查询时临时去重,写法为<% s.categories.distinct.each do |c| %>,但推荐直接修改关联定义,后续所有调用该关联的地方都会自动生效,无需重复写去重逻辑。

内容的提问来源于stack exchange,提问作者G. F. Hopper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:57:05