在Rails 3中处理多对多关系时如何找到正确的嵌套资源

时间:2013-02-18 21:19:29

标签: ruby-on-rails ruby-on-rails-3 join nested-resources

忍受我,因为我是一个Rails noob。我有一个基本的联赛系统。联赛 - >季节 - >分部 - >团队。我希望我的部门和团队属于任何一个季节。我的模型如下......

class Season < ActiveRecord::Base
  belongs_to :league
  has_many :season_division_teams
  has_many :divisions, :through => :season_division_teams
end

class Division < ActiveRecord::Base
  belongs_to :league
  has_many :seasons, :through => :season_division_teams
  has_many :season_division_teams
  has_many :teams, :through => :season_division_teams
end

class Team < ActiveRecord::Base
  belongs_to :league
  has_many :season_division_teams
  has_many :seasons, :through => :season_division_teams
  has_many :divisions, :through => :season_division_teams
end

class SeasonDivisionTeam < ActiveRecord::Base
  belongs_to :season
  belongs_to :division
  belongs_to :team
end

我希望最终能够做到的是,因为我在赛季'1',我有什么分区,然后给出了这些分区,球队是这些分区的一部分(对于给定的赛季)。

Season.Find(1).divisions.all do |division|
    # Do something with the teams that make of the division (for that season)
    # division.teams.count
end

我无法理解如何在Rails中执行此操作,这对我来说在SQL中看起来非常简单。

提前感谢您的帮助。

编辑:

只是为了澄清一点,我正在努力让球队参加一个赛季(他们的分区)。凭借我的模特,我知道我可以获得特定赛季的分区。我只需要那些分区和赛季的球队。

再次感谢。

1 个答案:

答案 0 :(得分:1)

使用includeseager-load关联,并避免在获得团队时遇到N + 1的性能影响:

@season = Season.includes(:divisions => :teams).find(1)
divisions = season.divisions
teams = divisions.map(&:teams).flatten.uniq

如果你想让那个季节的所有部门和团队只有,那么就这样做吧。首先,在Season模型中添加以下行:

has_many :teams, :through => :season_division_teams

现在你可以做到:

@season = Season.find(1)
divisions = @season.divisions
teams = @season.teams

请注意,此处急切加载并不多,因为数据库只会被击中两次(而不是每次击中一次,然后再一次)。

<强>更新

最后,如果你想获得本赛季的所有赛区,然后是那个赛季的所有赛区,请按以下步骤进行。您可以使用此代码:

@season = Season.find(1)                     
divisions = @season.divisions
divisions.each do |division|
  puts "Division: #{division.name}"
  division.teams.where(:season_division_teams => {:season_id => @season.id}).each do |team|
    puts "Team: #{team.name}"
  end
end

但使用eager-loading是首选方法,如下所示:

@season = Season.find(1)                     
divisions = @season.divisions.includes(:season_division_teams => :teams).
                    where(:divisions => {:season_division_teams => {:season_id => @season.id}})
divisions.each do |division| 
  puts "Division: #{division.name}"
  division.teams.each do |team|
    puts "Team: #{team.name}"
  end
end

这应该急切地为符合我们合并条件的相关部门加载所有团队。