Rails中如何显示最后几个无重复的PriceLog记录并消除重复显示?
解决PriceLog重复显示并展示最近记录的问题
问题根源分析
你的代码出现重复显示的核心原因有两个:
- 外层循环遍历的是所有PriceLog记录,而非去重的日期——如果三个产品在同一天都有价格记录,这个循环会执行3次,导致同一日期的行重复渲染3次。
- 每次在产品循环里重复查询数据库,不仅效率低下,还会因为多次取
last导致逻辑混乱,最终出现重复内容。
解决方案
我们可以通过优化控制器数据预加载和视图逻辑来解决问题,同时实现只展示最近N个(比如2个)日期的记录。
第一步:优化控制器的new方法
修改new方法,预加载所需数据,避免N+1查询,同时获取最近的不重复日期:
def new @pricelog = PriceLog.new @products = Product.all # 获取最近2个不重复的日期(可根据需求修改limit的值) @recent_dates = PriceLog.distinct.order(price_date: :desc).limit(2).pluck(:price_date) # 预加载指定日期内的所有价格记录,按【产品ID+日期】分组,方便视图快速获取 @price_logs = PriceLog.where(price_date: @recent_dates) .includes(:product) .group_by { |pl| [pl.product_id, pl.price_date] } end
第二步:修改_index.html.erb视图
重写视图逻辑,基于预加载的数据渲染,避免重复和冗余查询:
<table class="table table-hover"> <thead> <tr> <th>Date</th> <% @products.each do |product| %> <th><%= product.name %></th> <!-- 替换成你产品的显示字段,比如name --> <% end %> </tr> </thead> <tbody> <% @recent_dates.each do |date| %> <tr> <!-- 显示日期 --> <td><%= date.strftime('%d-%B-%Y') %></td> <!-- 遍历每个产品,显示对应日期的价格 --> <% @products.each do |product| %> <td> <% # 从预加载的分组数据中获取对应记录 %> <% log_entry = @price_logs[[product.id, date]]&.last %> <%= log_entry ? log_entry.price : 'No data' %> <!-- 无数据时显示提示 --> </td> <% end %> </tr> <% end %> </tbody> </table>
优化后的逻辑说明
- 去重日期:通过
distinct和limit获取最近的N个唯一日期,确保每行对应一个日期,不会重复。 - 预加载数据:一次性查询所需的所有PriceLog记录并分组,避免视图中重复查询数据库,提升性能。
- 清晰的视图结构:先按日期遍历行,再按产品遍历列,每个单元格对应一个产品在该日期的价格,逻辑清晰且无重复。
内容的提问来源于stack exchange,提问作者Bharat Mane
相关产品推荐
相关产品推荐

