EasierSaidThanDone
EasierSaidThanDone

Reputation: 1897

Modeling a 2:n relationship effectively in Rails

Here's the what I've got:

I have a model Match and a model Team. A Match has home_team and away_team. In fact it's a 2:n relationship.

class Team < ActiveRecord::Base
 has_many :home_matches, :class_name => 'Match', :foreign_key => 'home_team_id'
 has_many :away_matches, :class_name => 'Match', :foreign_key => 'away_team_id'

 public
 def matches
   return home_matches + away_matches
 end
end

and

class Match < ActiveRecord::Base
 attr_accessible :away_team_id, :home_team_id
 belongs_to :home_team, :class_name => 'Team', :foreign_key => 'home_team_id'
 belongs_to :away_team, :class_name => 'Team', :foreign_key => 'away_team_id'

end

Effectively I can now call Team.find(2).matches and get all away and home matches. But what I don't like is that it needs two SQL queries instead of one:

SELECT `matches`.* FROM `matches` WHERE `matches`.`home_team_id` = 2
SELECT `matches`.* FROM `matches` WHERE `matches`.`away_team_id` = 2

How can I get Rails to use this query?

  SELECT `matches`.* FROM `matches` WHERE `matches`.`home_team_id` = 2 OR `matches`.`away_team_id` = 2

The other way around causes the same headache; If I define a method team that merges home_team and away_team I query the DB two times where only one query is necessary.

Upvotes: 1

Views: 138

Answers (1)

cdesrosiers
cdesrosiers

Reputation: 8892

def matches
    Match.where("home_team_id = ? OR away_team_id = ?", id)
end

Also, you don't need those foreign keys in the Match model. Those attributes are contained in the Match model itself and are therefore not foreign.

Upvotes: 3

Related Questions