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.

+1


source to share


2 answers


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.

+7


source


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

.

0


source







All Articles