Rails has_many自定义ActiveRecord关联

12

我有一个Teams模型和一个Fixtures模型。Fixtures模型有一个客场队和一个主场队。我按照这个答案的示例进行操作,大部分内容都可以工作。

class Fixture < ActiveRecord::Base
  belongs_to :home, class_name: 'Team'
  belongs_to :away, class_name: 'Team'
end


class Team < ActiveRecord::Base
  has_many :home_games, :class_name => 'Fixture', :foreign_key => 'home_id'
  has_many :away_games, :class_name => 'Fixture', :foreign_key => 'away_id'
end

我想能够调用@team.fixtures获得球队所有赛事的列表,目前@team.home_games给出主场比赛,@team.away_games给出客场比赛。 我该如何编写类似于has_many :home_gameshas_many :games,这是否是最好的方法?

1个回答

13
我认为最好的方法是编写一个实例方法来完成这个任务:an instance method
在Team模型中:
def games
  Fixture.where("home_id = ? OR away_id = ?", self.id, self.id)
end

像普通方法一样使用它:

Team.first.games
#=> [<Fixture id: ... >, <Fixture id: ... >, ... ]

这应该会返回一个 ActiveRecord::Relation,它可以被用于作用域链等重复使用。

(这里有一个类似的问题,但是针对的是 has_one 关联: Rails Model has_many with multiple foreign_keys)


此外,您还可以使用 Team 的 id(如果您已经拥有 team_id 而不是 Team 实例对象)来将其制作为一个类方法:

class Team < ActiveRecord::Base
  has_many :home_games, :class_name => 'Fixture', :foreign_key => 'home_id'
  has_many :away_games, :class_name => 'Fixture', :foreign_key => 'away_id'

  def games
    Team.games(self.id)
  end

  def self.games(team_id)
    Fixture.where('fixtures.home_id = ? OR fixtures.away_id = ?', team_id, team_id)    
  end
end

然后像这样使用它:

Team.games(params[:team_id])
# or
@team = Team.where(id: params[:id]).first
@team.games

3
我相信如果你这样做,你必须小心,因为你不能使用包含,并且可能会暴露出N+1个查询。 - JapanRob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接