sha*_*wbq 6 activerecord ruby-on-rails has-many-through ruby-on-rails-4
当在中间的关系上实现多个外键时,我很难从分层父关系中获取所涉及的游戏列表.
鉴于League Object NFC,找到它的所有Game对象[G1,G3,G4]
# id :integer not null, primary key
# name :string
class League
has_many :teams
# has_many :games, :through => :teams (Is there some way to do this?)
end
# id :integer not null, primary key
# team_name :string
# league_id :integer
class Team
belongs_to :league
has_many :home_games, :foreign_key => team_a_id, :source => :game
has_many :away_games, :foreign_key => team_b_id, :source => :game
end
# id :integer not null, primary key
# game_name :string
# team_a_id :integer not null
# team_b_id :integer not null
class Game
belongs_to :home_team, :class_name => Team
belongs_to :away_team, :class_name => Team
end
Run Code Online (Sandbox Code Playgroud)
数据示例:
LEAGUE - TEAM - GAME
---------------------------------
AFC -
PATRIOTS -
Home Away
G1(PATRIOTS vs DALLAS)
G2(PATRIOTS vs PITTSBURG)
PITTSBURG -
G2(PATRIOTS vs PITTSBURG)
NFC -
DALLAS -
G1(PATRIOTS vs DALLAS)
G3(DALLAS vs GREENBAY)
G4(DALLAS vs SEATTLE)
GREENBAY
G3(DALLAS vs GREENBAY)
SEATTLE
G4(DALLAS vs SEATTLE)
Run Code Online (Sandbox Code Playgroud)
答案将包含符合Rails 4的答案.如果Rails 4替代方案效率非常低,则可以特别考虑RAILS 5的答案.
nfc = League.where(name: 'NFC').first
# <answer>
puts nfc.games
## array containing objects [G1,G2,G3]
Run Code Online (Sandbox Code Playgroud)
我所遇到的挑战是来自外键的home_team/ away_team和组合数据.
我要给出一个答案,因为 @meagar 的第一个解决方案需要两个 SQL 查询而不是一个(另外,如果联盟没有球队,这不是一个 SQL 语法错误吗?),第二个解决方案将包含重复的如果两支球队来自同一联赛,则比赛实例。
一般来说,我会尽量避免在可重用范围中进行连接,因为它们会强制查询达到某种“形状”。所以我会写这样的东西:
class Game
# ...
scope :for_league, ->(league_id) {
where(<<-EOQ, league_id)
EXISTS (SELECT 1
FROM teams t
WHERE t.id IN (games.team_a_id, games.team_b_id)
AND t.league_id = ?)
EOQ
}
# ...
end
Run Code Online (Sandbox Code Playgroud)
顺便说一句,这种 SQL 技术称为“相关子查询”。我承认第一次看到它时看起来很奇怪,但这是很正常的事情。您可以看到子查询“伸出”到引用games。您的数据库优化它应该没有问题(当然给定外键上的索引),但从概念上讲,它在表中的每行运行一次子查询games。
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |