2012-03-22 3 views
5

пытается реорганизовать код для обеспечения чистого ОБЪЕДИНЕНИЯRails 3.2.2 - has_many через

ИГРА имеет HOME_TEAM и AWAY_TEAM

КОМАНДА имеет много игр, как HOME_TEAM или AWAY_TEAM

ассоциация между GAME и TEAM - прямолинейный HABTM, но мне нужно указать, какой из двух TEAMS, связанных с GAME, является HOME_TEAM и который является AWAY_TEAM. Я сделал это, добавив дополнительные поля и ассоциации, но это очевидно очень мокрое, а не сухое. Я знаю, что ответ проходит, но у меня, похоже, произошел кризис мозга, и я не могу полностью обдумать это.

В основном я хочу, чтобы иметь возможность делать Game.teams (возвращает коллекцию обеих команд) и Game.home_team (получить и установить КОМАНДУ в HOME_TEAM) и Game.away_team (получить и установить КОМАНДА для AWAY_TEAM)

Извините поставить такой простой запрос звучащий, но это только что получил от меня

class Game < ActiveRecord::Base 
    belongs_to :home_team 
    belongs_to :away_team 
    has_and_belongs_to_many :teams 
end 

class HomeTeam < ActiveRecord::Base 
    belongs_to :team 
    has_one :games 
end 

class AwayTeam < ActiveRecord::Base 
    belongs_to :team 
    has_one :games 
end 

class Team < ActiveRecord::Base 
    has_and_belongs_to_many :games 
    has_many :away_teams 
    has_many :home_teams 
end 

Все помощь высоко оценили

Питер

+2

Вы действительно хотите, чтобы HomeTeam и AwayTeam были отдельными классами? И, в настоящее время, отдельные таблицы БД? – Chowlett

+0

Нет - это просто уловка. Я, наверное, хочу таблицу games_teams с home_team boolean, я думаю ... – pshear0

ответ

7

Чтобы сделать то, что вы хотите сделать, вы должны использовать has_many :through вместо hatbm. См. here для получения дополнительной информации. Короче говоря, хорошо, что вы можете добавить другие переменные в таблицу соединений. В вашем случае булевое имя home_team.

Итак, вот что я сделал бы. Во-первых, создать таблицу ассоциации (так как у меня нет большого воображения, я буду называть его участие):

create_table :participations, do |t| 
    t.integer :game_id, :null => false 
    t.integer :team_id, :null => false 
    t.boolean :home_team 
end 

Как вы можете видеть, в отличие от вашего стола gamesteams, это один имеет идентификатор. И вы можете добавить к нему атрибуты. Тогда, я хотел бы использовать эти модели:

class Participation < ActiveRecord::Base 
    belongs_to :game 
    belongs_to :team 
end 

class Game < ActiveRecord::Base 
    has_many :participations, :dependent => :destroy 
    has_many :teams, :through => :participations 
end 

class Team < ActiveRecord::Base 
    has_many :participations, :dependent => :destroy 
    has_many :games, :through => :participations 
end 

Так, чтобы получить команды в игре, вы @game.teams.

Теперь, чтобы получить HOME_TEAM и AWAY_TEAM, добавить эти методы для вашей модели игры:

def home_team 
    self.teams.joins(:participations).where("participations.home_team IS ?", true).first 
end 

def away_team 
    self.teams.joins(:participations).where("participations.home_team IS ?", false).first 
end 

И тогда вы будете в состоянии сделать @game.home_team и @game.away_team.

редактировать Петр: Хорошо, так что для MySQL вам придется использовать различные где заявление:

self.teams.joins (участники): .гд ("? Participants.home_team =", правда,). Сначала self.teams.joins (: участники). где («members.home_team IS NULL»). first

Я могу использовать «=?», true и «! =?», true - ИЛИ - НЕ НУЛЛ и IS NULL

Я думаю, что для ложных вы должны попробовать использовать where("participants.home_team = ?", false)

Хорошо, так что существует как минимум 2 способа настроить свои команды.

  1. Вы позволить пользователю выбрать, какая команда играет дома
  2. Вы предполагаете, первая команда является хозяевам

Если вы идете на номер 1, вы должны использовать переключатель, чтобы позволить пользователь решает. Что-то вроде этого:

<%= label_tag :home, 'Home Team' %><br /> 
<%= label_tag :home_team_1, 'Team 1' %><%= radio_button_tag :home_team, 1 %> 
<%= label_tag :home_team_2, 'Team 2' %><%= radio_button_tag :home_team, 2 %> 

Так что если params[:home_team] == 1, то первая команда хозяев поля, если params[:home_team] == 2, то вторая команда хозяев поля.

Если вы идете на номер 2, то вы должны иметь что-то подобное в вашей форме действительно добавить команды к игре:

<%= label_tag :name, 'Home Team' %> 
    <%= text_field_tag :name, nil, :name => "home[]" %> 

    <%= label_tag :name, 'Away Team' %> 
    <%= text_field_tag :name, nil, :name => "away[]" %> 

Итак, в вашем контроллере вы можете сделать что-то вроде

@game = Game.new(params[:game]) 

home = Team.create(params[:home]) 
# or 
home = Team.find_or_create_by_name(params[:home][:name]) 
@game.participations.create(:team_id => home.id, :home_team => true or 1) 

away = Team.find_or_create_by_name(params[:away][:name]) 
@game.participations.create(:team_id => away.id, :home_team => false or 0) 
+0

Ashitaka - это звучит очень многообещающе. Когда мы говорим, я вхожу в свою тестовую кровать. Сообщите, если это сработает и примет. Спасибо за ваш ответ – pshear0

+0

Я отредактировал мой вопрос и действительно протестировал его на этот раз. Он работает правильно, дайте ему попробовать и расскажите мне, как все прошло! – Ashitaka

+0

Привет, Ашитака, все еще работая над этой проблемой. Используя ваше решение, я столкнулся с проблемами с MySql и должен был внести пару изменений в пункты where – pshear0

Смежные вопросы