我有一个多对多的关系:
Player
has_many :team_players
has_many :teams, through: :team_players
Team
has_many :team_players
has_many :players, through: :team_players
TeamPlayer
belongs_to :team
belongs_to :player
玩家可以执行的一个动作是加入一个团队。这只会创建一个新的TeamPlayer
记录,其中包含team_id + player_id
(状态为“active”)。当一个玩家加入一个团队时,我希望端点响应玩家+该玩家所在的所有团队。
在玩家加入团队时,我还没有检索到玩家记录,我用team_id + player_id
创建了加入记录。
我知道我可以先得到球员,然后做一些类似于player.teams的事情,但是我想学习如何用teams记录获取适当的球员(整个球员记录),并且只从Team表中提取'name'列。
我试过Player.find(player_id).joins(:teams).pluck(:name)
,但这不起作用。我觉得连接的地方不对。我在想这样的事情:Player.joins(:teams).pluck(:name)
但不知道在哪里放播放器ID。会是where从句吗
我在搜索时也看到了这样的语法:Player.teams.where...
但也不知道如何使用。
所以基本上我希望最终的结果是这样的:
player {
// player fields...
teams: ['team-1', 'team-2', etc...],
}
编辑
这个查询起作用了:
Player.where(id: player_id).includes(:teams).pluck(:name).first
但这只返回一个球队名称数组(球员是其中的一部分)。我希望球队列表嵌套在球员对象中
---最终模型---
对于任何好奇的人来说,这就是最终模型的样子:
class Player < ApplicationRecord
# relations
# - need this association to do join queries
has_many :team_players
has_many :teams, through: :team_players
has_many :active_team_players,
-> { where(status: TeamPlayer.status[:active]) },
class_name: 'TeamPlayer'
has_many :active_teams,
through: :active_team_players,
source: :team
def self.get_with_teams(player_id)
Player
.left_joins(:active_teams)
.group(:id)
.select(
'players.*',
'json_agg(teams.name) AS team_names'
)
.find(player_id)
end
end
1条答案
按热度按时间cmssoen21#
不是你想要的
pluck
用于立即触发数据库查询,并仅以数组的形式获取所选列。除非它在一个已经加载的关系上被调用,实际上就像#map
一样工作。这是一个基于表的世界
如果你想从一个连接的表中选择多个值到结果中的一个列中,你需要一个聚合函数。例如,在Postgres上,你可以选择一个包含所有团队名称的数组:
在其他数据库上,您可能需要使用其他聚合函数。但是,您可能希望保留这种方法,直到出于性能原因而实际需要使用它,并使用
.includes
/.eager_load
。Player.eager_load(:teams)
实际上选择了两个表中的列-实际上为每个团队选择了一行,以及来自玩家的列:结果中的每一行都将类似于:
Rails实际上会循环遍历结果,并将其全部填充到Player和Team记录中,以便您可以专注于更有趣的内容:
Scoping关联
所有上述仍然只是得到所有的球队。如果您只想要活跃的团队,则可以添加其他关联:
当你连接
active_teams
时,它会在join子句中添加一个条件: