Multilevel associations in rails
I am creating an application to track soccer teams throughout the season. but i am stuck on database design. One match has a home team and an away team. I've created a fixture model that has two foreign keys, home_team and away_team, but I can't get the association to work correctly. any ideas? Each final belongs to a league.
Simple answer:
class Fixture < ActiveRecord::Base
belongs_to :home_team, :class_name => "Team", :foreign_key => :home_team
belongs_to :away_team, :class_name => "Team", :foreign_key => :away_team
end
class Team < ActiveRecord::Base
has_many :fixtures
end
But that's not good if you do, because Team.fixtures won't work.
class Team < ActiveRecord::Base
has_many :home_fixtures, :class_name => "Fixtures", :foreign_key => :home_team
has_many :away_fixtures, :class_name => "Fixtures", :foreign_key => :away_team
end
will give you two collections ... but combining them must happen in ruby, which will be frustrating.
class Team < ActiveRecord::Base
def fixtures(*args)
home_fixtures.all(*args) + away_fixtures.all(*args)
end
end
He's in trouble too, sorting and limiting will all be jammed (heh, pun, who knew?).
class Team < ActiveRecord::Base
has_many :fixtures, :finder_sql => 'SELECT * FROM fixtures where (home_team = #{id} or away_team = #{id})'
has_many :home_fixtures, :class_name => "Fixtures", :foreign_key => :home_team
has_many :away_fixtures, :class_name => "Fixtures", :foreign_key => :away_team
end
It's ugly, but it might just work. Finder_sql seems to do what it needs to do.
Another option is to use named_scope:
class Fixture < ActiveRecord::Base
named_scope :for_team_id, lambda{|team_id| {:conditions => ['(home_team = ? or away_team = ?)', team_id, team_id]} }
belongs_to :home_team, :class_name => "Team", :foreign_key => :home_team
belongs_to :away_team, :class_name => "Team", :foreign_key => :away_team
end
class Team < ActiveRecord::Base
def fixtures
Fixtures.for_team_id(id)
end
end
The last solution is the one I would stick with because it is a scope that will behave like a read-only association and prevent wackiness :finder_sql
that can happen further down the line (I mean really? Does it know how to merge more conditions? Sometimes it's a subquery, a subquery? Is it just not needed here?).
Hope it helps.
source to share
Say you have a model Team
and a model Something
, the latter will have home_team_id
and away_team_id
.
class Something < ActiveRecord::Base
belongs_to :home_team, :class_name => 'Team'
belongs_to :away_team, :class_name => 'Team'
You will call them like something.away_team
and something.home_team
.
source to share