ruby-on-rails - 预加载连接多个值的记录
问题描述
我有一个应用程序可以帮助网球运动员找到对手。我有以下型号:
TennisMatch (id, description, user_id)
User (id, name, type)
AvailabilityWindow(tennis_match_id, start_time, end_time, requester_id)
用户可以使用该应用发布网球比赛列表。作为其中的一部分,他们必须提供一些可用性。例如,如果他们想在周六上午 8 点到 10 点之间进行比赛。这将创建一个可用性记录作为创建匹配的一部分:
AvailabilityWindow.new(tennis_match_id: 1, start_time: '8am Saturday', end_time: '10am Saturday', requester_id: user.id)
如果其他玩家看到列表,他们可以接受并同意在建议的时间和日期进行游戏。他们还可以建议其他可用性,这将导致将记录添加到 AvailabilityWindow 表中。因此,一场网球比赛可以有来自多个不同用户的多个 availability_window 记录。
我的问题是:我需要一个页面,列出所有网球比赛以及创建列表的用户建议的可用性(忽略其他用户建议的任何可用性)。例如
class TennisMatch < ApplicationRecord
has_many :availability_windows
end
class TennisMatchController < ApplicationController
def index
@tennis_matches = TennisMatch.all
end
end
index.html.erb:
<% @tennis_matches.each do |match| %>
<h4><%= match.description %>
<% match.availability_windows.where(requester_id: match.user_id).each do |window| %>
<p><%= window.start_time %>-<%= window.end_time %>
<% end %>
<% end %>
这确实有效,但会受到 n+1 的影响,因为它会查询每个匹配项以获取可用性。如何预加载这些数据以避免 n+1?
我们还假设简单地预加载所有窗口,例如TennisMatch.all.includes(:availability_windows)
在控制器中,并select(&block)
在视图中对集合执行 a 以避免查询不是一种选择。
解决方案
尝试这个:
class TennisMatchController < ApplicationController
def index
matches = TennisMatch.all
user_ids = matches.pluck(:user_id)
@tennis_matches = matches.includes(:availability_windows).
where(availability_windows: { user_id: user_ids })
end
end
然后在 index.html.erb 中:
<% @tennis_matches.each do |match| %>
<h4><%= match.description %>
<% match.availability_windows.each do |window| %>
<p><%= window.start_time %>-<%= window.end_time %>
<% end %>
<% end %>
推荐阅读
- assembly - 用于虚拟到物理地址转换的 FreeBSD 模块
- microsoft-graph-api - 从 Azure 数据工厂管道调用 MS Graph API
- node.js - 如何处理停止发送数据的 HTTP 请求
- ruby-on-rails - 如何在 RoR 中锁定记录
- python - 试图弄清楚如何传递函数,以便它可以显示值
- database - 保存用户是否在 MongoDB 中做过某事的条件:我应该使用哪种字段类型?
- javascript - 为页面上多种类型的元素添加监听器和值
- spring - 在 Feign 客户端中设置 cookie
- go - go env 显示 GOPATH 不匹配
- javascript - 如何在 react.js 中传递数据/值名称