2017-01-27 7 views
2

ich folgende Modelle habenRails 5 Update has_many durch assoziierte Modelle

class TeamPlayer < ApplicationRecord 
    belongs_to :team 
    belongs_to :player 
    belongs_to :role 
end 

class Team < ApplicationRecord 
    has_many :team_players 
    has_many :players, :through => :team_players 
end 

class Role < ApplicationRecord 
    has_many :team_players 
    has_many :players, :through => :team_players 
end 

class Player < ApplicationRecord 
    has_many :team_players 
    has_many :teams, :through => :team_players 

    has_many :roles, :through => :team_players 
end 

Grundsätzlich möchte ich verschiedene Rollen zu verschiedenen Spielern in einem Team vergeben.

id team_id  player_id role_id 
2 1   2   1 
3 3   2   1 
4 1   1   2 

Was sollte es aussehen in meinem teams_controller.rb neue Spieler mit einer Rolle hinzufügen, einen Spieler mit neuer Rolle zu aktualisieren und das Spieler aus meinem Team zu entfernen?

+0

Eine Frage und ein Kommentar: So wie Sie es im Moment eingerichtet haben, kann ein Spieler zu mehreren Teams gehören. Willst du es so? Wenn dies der Fall ist, müssen Sie, da ein Spieler auch mehrere Rollen haben kann, einen Weg finden, um zu bestimmen, für welches Team der Spieler eine bestimmte Rolle hat. Es kommt darauf an, die Rollenattribute in Team zu verschachteln und nur eine Rolle im Kontext eines Teams zu erstellen. Wenn ein Spieler nur einem Team angehören kann, ist Ihre Lösung etwas einfacher, glaube ich. – eggroll

+0

Aber in diesem Design kann ein Spieler zu vielen Teams durch ': team_players' gehören. Zum Beispiel: 'Team A' hat" Spieler 1 "an" Team B "ausgeliehen, er gehört immer noch zu" Team A ", aber Status oder Rolle hat sich geändert. – ln9187

Antwort

1

Dies ist nur der Anfang einer möglichen Lösung und ähnelt sehr dem, was Sie bei einigen Modell- und Datenbankvalidierungen haben. Einige dieser Validierungen stellen die Eindeutigkeit jeder Drei-Wege-Beziehung sicher (FilledTeamRole), so dass entweder der Fehler beim Versuch, einen doppelten Datensatz zu erstellen, behandelt werden muss oder die möglichen IDs jeder Klasse, die ausgewählt werden könnte, so gefiltert werden, dass a Duplikat kann nicht erstellt werden.

Eine vollständige Lösung hängt davon ab, welche anderen Assoziationen zwischen den Klassen Team, Player und Role außer einer, die alle drei erfordert. Möchten/benötigen Sie beispielsweise eine Zuordnung zwischen Team und Player, wobei eine Beziehung zwischen nur diesen beiden Klassen besteht, ohne dass ein Role (TeamPlayerid: 1, team_id: 1, player_id: 1) erforderlich ist. Wenn diese Beziehungen gewünscht sind, wird zusätzlicher Code benötigt, um dies zu erreichen, was ich als Vorschlag habe und anbieten kann.

Soweit, was Ihr Controller aussehen würde, können Sie die filled_team_roles Controller verwenden könnte (oder vielleicht ein Dashboard-Controller erstellen), @teams Instanzvariablen liefern, @players und @roles zu Dropdown-Menüs für jede Klasse in einem Formular füllen zu Erstellen Sie die filled_team_roles Beziehung. Sie könnten auch zusätzliche Formulare innerhalb jeder der anderen Klassen haben, in denen Sie mit zwei Dropdowns anstelle von drei mit dem dritten Wert die ausgewählte Modell-ID der Klasse verwenden, deren Controller das Formular enthält (z. B. die edit Aktion in der players_controller mit Drop- downs für team und role)

~/app/models/team.rb

class Team < ApplicationRecord 
    has_many :filled_team_roles, dependent: :destroy 
    validates :name, uniqueness: { scope: [:sport, :city] } 
    scope :by_name_asc, -> { order(name: :asc) } 
end 

~/app/models/player.rb

class Player < ApplicationRecord 
    has_many :filled_team_roles, dependent: :destroy 
    validates_uniqueness_of :ssn 
    scope :by_name_asc, -> { order(last_name: :asc, first_name: :asc) } 
end 

~/app/models/role.rb

class Role < ApplicationRecord 
    has_many :filled_team_roles, dependent: :destroy 
    validates_uniqueness_of :name 
    scope :by_name_asc, -> { order(name: :asc) } 
end 

~/app/models/filled_team_role.rb

class FilledTeamRole < ApplicationRecord 
    belongs_to :team 
    belongs_to :player 
    belongs_to :role 
    validates :team_id, presence: true 
    validates :player_id, presence: true 
    validates :role_id, presence: true 
    validates :team_id, uniqueness: { scope: [:player_id, :role_id] }  
end 

~/db/Migration/20170127041000_create_team.rb

class CreateTeam < ActiveRecord::Migration[5.0] 
    def change 
    create_table :teams do |t| 
     t.string :name 
     t.string :sport 
     t.string :city 
     t.string :state 
     t.string :country 
     t.timestamps null: false 
    end 
    add_index :teams, [:name, :sport, :city], unique: true 
    end 
end 

~/db/migrate/20170127041100_create_player.rb

class CreatePlayer < ActiveRecord::Migration[5.0] 
    def change 
    create_table :players do |t| 
     t.string :first_name 
     t.string :last_name, index: true 
     t.string :full_name_surname_first 
     t.string :ssn, index: { unique: true } 
     t.timestamps null: false 
    end 
    end 
end 

~/db/Migration/20170127041200_create_role.rb

class CreateRole < ActiveRecord::Migration[5.0] 
    def change 
    create_table :roles do |t| 
     t.string :name, index: { unique: true } 
     t.timestamps null: false 
    end 
    end 
end 

~/db/Migration/20170127051300_create_filled_team_role.rb

class CreateFilledTeamRole < ActiveRecord::Migration[5.0] 
    def change 
    create_table :filled_team_roles do |t| 
     t.timestamps null: false 
     t.references :team 
     t.references :role 
     t.references :player 
    end 
    add_index :filled_team_roles, 
      [:team_id, :player_id, :role_id], 
       unique: true, 
       name: 'index_filled_team_roles_unique_combination_of_foreign_keys' 
    end 
end 

~/db/samen.rb

Team.create(name: 'Los Angeles Dodgers', sport: 'baseball', city: 'Los Angeles', state: 'CA', country: 'United States') 
Team.create(name: 'New York Yankees', sport: 'baseball', city: 'New York', state: 'NY', country: 'United States') 
Team.create(name: 'Chicago Cubs',  sport: 'baseball', city: 'Chicago',  state: 'IL', country: 'United States') 
Team.create(name: 'St. Louis Cardinals', sport: 'baseball', city: 'St. Louis', state: 'MO', country: 'United States') 
Player.create(first_name: 'Max', last_name: 'Walker', full_name_surname_first: 'Walker, Max', ssn: '123-45-6789') 
Player.create(first_name: 'Homer', last_name: 'Winn', full_name_surname_first: 'Winn, Homer', ssn: '234-56-7890') 
Player.create(first_name: 'Will', last_name: 'Steel', full_name_surname_first: 'Steel, Will', ssn: '345-67-8901') 
Player.create(first_name: 'Lucky', last_name: 'Snag', full_name_surname_first: 'Snag, Lucky', ssn: '456-78-9012') 
Role.create(name: 'pitcher') 
Role.create(name: 'catcher') 
Role.create(name: 'first baseman') 
Role.create(name: 'second baseman') 
Role.create(name: 'shortstop') 
Role.create(name: 'third baseman') 
Role.create(name: 'right fielder') 
Role.create(name: 'center fielder') 
Role.create(name: 'left fielder') 
FilledTeamRole.create(team_id: 1, player_id: 1, role_id: 1) 
FilledTeamRole.create(team_id: 2, player_id: 2, role_id: 2) 
FilledTeamRole.create(team_id: 3, player_id: 3, role_id: 3) 
FilledTeamRole.create(team_id: 4, player_id: 4, role_id: 4) 
+0

Bitte beachten Sie, dass ich eine Korrektur in der akzeptierten Version der Antwort vorgenommen habe und dabei 'validates: team_id, uniqueness: {scope: [: player_id,: position_id]}' im 'fill_team_role' Modell mit' validates: team_id, uniqueness: {scope: [: player_id,: role_id]} '. – eggroll

Verwandte Themen