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
(TeamPlayer
id: 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)
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
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