2012-03-22 32 views
5

cố gắng để cấu trúc lại mã để cung cấp liên kết sạchRails 3.2.2 - has_many qua

một trò chơi có một HOME_TEAM và một đấu với AWAY_TEAM

Một TEAM có nhiều trò chơi như một HOME_TEAM hoặc một đấu với AWAY_TEAM

Hiệp hội giữa GAME và TEAM là một HABTM NHƯNG thẳng về phía trước tôi cần biểu thị hai TEAM nào liên quan đến GAME là HOME_TEAM và AWAY_TEAM. Tôi đã làm điều đó bằng cách thêm các lĩnh vực và hiệp hội bổ sung nhưng điều này rõ ràng là rất ẩm ướt hơn là khô. Tôi biết câu trả lời là thông qua nhưng tôi dường như đã có một cuộc khủng hoảng não và không thể có được khá đầu của tôi vòng này.

Về cơ bản tôi muốn để có thể làm Game.teams (trả về bộ sưu tập của cả hai đội) và Game.home_team (get và set một TEAM để HOME_TEAM) và Game.away_team (get và set một TEAM để đấu với AWAY_TEAM)

Xin lỗi vì đã đặt ra như một truy vấn âm đơn giản nhưng nó chỉ có xa tôi

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 

Tất cả giúp rất nhiều đánh giá cao

Peter

+2

Bạn có thực sự muốn HomeTeam và AwayTeam trở thành các lớp riêng biệt không? Và, hiện tại, các bảng DB riêng biệt? – Chowlett

+0

Không - nó chỉ là một nhà nghỉ. Tôi có thể muốn một bảng games_teams với một boolean home_team tôi nghĩ rằng ... – pshear0

Trả lời

7

Để làm những gì bạn muốn làm, bạn nên sử dụng has_many :through thay vì hatbm. Xem here để biết thêm thông tin. Tóm lại, điều tốt là bạn có thể thêm các biến khác vào bảng kết nối. Trong trường hợp của bạn, một boolean gọi là home_team.

Vì vậy, đây là những gì tôi sẽ làm. Trước tiên, hãy tạo một bảng liên kết (vì tôi không có nhiều trí tưởng tượng, tôi sẽ gọi nó là sự tham gia):

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

Như bạn thấy, không giống như bảng gamesteam, thẻ này có id. Và bạn có thể thêm các thuộc tính vào nó. Sau đó, tôi sẽ sử dụng các mô hình này:

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 

Vì vậy, để có được các đội bóng của một trò chơi, bạn làm @game.teams.

Bây giờ, để có được HOME_TEAM và đấu với AWAY_TEAM, thêm các phương pháp để mô hình trò chơi của bạn:

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 

Và sau đó bạn sẽ có thể làm @game.home_team@game.away_team.

Phêrô chỉnh sửa: Ok, vậy cho mysql bạn sẽ phải sử dụng khác nhau, nơi báo cáo:

self.teams.joins (: người tham gia) .where ("? Participants.home_team =", true) .first self.teams.joins (: người tham gia) .tại đây ("particip.home_team IS NULL") đầu tiên

Tôi có thể sử dụng "=?", true và "! =?", đúng - HOẶC-- KHÔNG phải là NULL và IS NULL

Tôi cho rằng bạn nên thử sử dụng where("participants.home_team = ?", false)

Ok, do đó, có ít nhất 2 cách để thiết lập nhóm của bạn.

  1. Bạn cho phép người dùng chọn đội đang chơi nhà
  2. Bạn phải chịu đội đầu tiên là đội chủ nhà

Nếu bạn đi cho số 1, bạn nên sử dụng một nút radio để cho các người dùng quyết định. Một cái gì đó như thế này:

<%= 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 %> 

Vì vậy, nếu params[:home_team] == 1, nhóm nghiên cứu đầu tiên là đội chủ nhà, nếu params[:home_team] == 2, nhóm thứ hai là đội chủ nhà.

Nếu bạn đi cho số 2, sau đó, bạn nên có một cái gì đó như thế này trong hình thức của bạn làm thêm các đội bóng đến trò chơi của bạn:

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

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

Vì vậy, sau đó trong bộ điều khiển của bạn, bạn có thể làm điều gì đó như

@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 - điều này nghe có vẻ rất hứa hẹn. Đang xây dựng vào giường thử nghiệm của tôi khi chúng tôi nói chuyện. Sẽ cho bạn biết nếu điều này hoạt động và chấp nhận. Cảm ơn phản hồi của bạn – pshear0

+0

Tôi đã chỉnh sửa câu hỏi của mình và thực sự đã thử nghiệm nó lần này. Nó hoạt động chính xác, hãy thử và cho tôi biết nó đã hoạt động như thế nào! – Ashitaka

+0

Xin chào Ashitaka, vẫn đang nghiên cứu vấn đề này. Sử dụng giải pháp của bạn, tôi đã gặp phải vấn đề với MySql và phải thực hiện một vài thay đổi đối với các mệnh đề where – pshear0

Các vấn đề liên quan