Многоуровневые ассоциации в рельсах
Я создаю приложение для отслеживания футбольных команд в течение всего сезона. но я застрял на дизайне базы данных. В одном матче есть команда хозяев и команда гостей. Я создал модель прибора, у которой есть два внешних ключа - home_team и away_team, но я не могу заставить ассоциацию работать правильно. есть идеи? Каждый матч принадлежит лиге.
2 ответа
Простой ответ:
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
Но это не хорошо, если вы, потому что Team.fixtures не будет работать.
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
даст вам две коллекции... но их объединение должно произойти в рубине, что будет неприлично.
class Team < ActiveRecord::Base
def fixtures(*args)
home_fixtures.all(*args) + away_fixtures.all(*args)
end
end
С этим тоже есть свои проблемы, сортировка и лимит будут забиты (хех, каламбур, кто знал?).
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
Это некрасиво, но может просто сработать. Похоже, что finder_sql делает то, что нужно.
Другой вариант - использовать 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
Это последнее решение, которое я придерживаюсь, потому что это область действия, которая будет вести себя как ассоциация только для чтения, и предотвращает :finder_sql
причудливость, которая может произойти в дальнейшем (я имею в виду на самом деле? Как он знает, как объединить больше условий? Иногда он делает подзапрос, подзапрос? Это просто не нужно здесь?).
Надеюсь это поможет.
Скажи, что у тебя есть Team
модель и Something
Модель, последняя будет иметь home_team_id
а также away_team_id
,
class Something < ActiveRecord::Base
belongs_to :home_team, :class_name => 'Team'
belongs_to :away_team, :class_name => 'Team'
Вы будете ссылаться на них как something.away_team
а также something.home_team
,