Rails电影租赁应用:实现影片及可用库存数量统计展示
解决Rails电影租赁应用中重复显示影片及统计可用库存的问题
我来帮你搞定这个问题!你现在遇到的核心问题是遍历库存记录导致同一部影片重复渲染——因为每一条库存记录都关联着同一个影片,自然会重复输出。我们需要调整查询逻辑,直接从Film模型入手,同时统计每部影片的可用库存数量,这样就能实现每部影片只显示一次的需求。
问题根源拆解
你当前的控制器取了所有Inventory记录,然后在视图里遍历每个库存、输出对应的影片信息。由于同一部影片对应多条库存记录(比如你示例里film_id=1有2条可用库存),所以同一部影片会被重复渲染多次,这就是问题所在。
最优解决方案:一次性查询影片+统计可用库存
我们可以用ActiveRecord的查询语句,一次性获取所有影片并同步统计每部的可用库存数,既避免N+1查询,也能解决重复显示的问题。
1. 修改Inventory控制器的index动作
把原来获取所有库存的逻辑,改成查询影片并统计可用库存:
def index # 查询所有影片,同时统计每部影片的可用库存数(包含库存为0的影片) @films = Film.left_joins(:inventories) .group('films.id') .select( 'films.*', "COUNT(CASE WHEN inventories.checkout_status = 'available' THEN inventories.inventory_id END) AS available_inventory_count" ) end
left_joins(:inventories):左连接影片和库存表,确保哪怕没有库存的影片也能被查询到group('films.id'):按影片ID分组,保证每部影片只返回一条记录- 带CASE的COUNT语句:只统计
checkout_status为available的库存数量,没有可用库存的影片会显示0
2. 更新视图代码
现在视图需要遍历@films而非@inventory,输出每部影片的信息和可用库存数:
<% @films.each do |film| %> <div class="film-card"> <h2><%= film.title %></h2> <p><%= film.description %></p> <p><strong>可用库存:</strong><%= film.available_inventory_count %></p> </div> <% end %>
备选方案:在Film模型中封装统计逻辑(注意性能)
如果你更习惯把业务逻辑放在模型层,可以在Film模型里添加一个方法计算可用库存,但要注意避免N+1查询:
# app/models/film.rb class Film < ApplicationRecord has_many :inventories def available_inventory_count inventories.where(checkout_status: 'available').count end end
然后控制器里要预加载库存来优化性能:
def index @films = Film.includes(:inventories).all end
视图代码和上面一致,调用film.available_inventory_count即可。不过这种方式在影片数量较多时,性能不如第一种一次性查询的方案,因为每部影片都会单独执行一次count查询。
验证效果
现在重启你的应用,就能看到每部影片只显示一次,并且正确对应可用库存数量了(比如你示例里的film_id=1会显示可用库存:2)。
内容的提问来源于stack exchange,提问作者pbybel
相关产品推荐
相关产品推荐

