Это только начало возможного решения, и оно очень похоже на то, что у вас есть, с добавленной валидностью модели и базы данных. Некоторые из этих валидаций обеспечивают уникальность каждой трехсторонней связи (FilledTeamRole
), поэтому нужно либо обработать ошибку при попытке создать дублируемую запись, либо вы можете отфильтровать возможные идентификаторы каждого класса, который можно выбрать, чтобы дубликат не может быть создан.
Полное решение будет зависеть от того, какие другие ассоциации вы хотите между классами Team
, Player
и Role
, отличными от тех, которые требуют всех трех. Например, вам нужна/нужна связь между Team
и Player
, где существует связь между этими двумя классами без необходимости Role
(TeamPlayer
id: 1, team_id: 1, player_id: 1
). Если эти отношения желательны, то для этого потребуется дополнительный код, который у меня есть и могу предложить в качестве предложения.
Насколько то, что ваш контроллер будет выглядеть, вы можете использовать контроллер filled_team_roles
(или, возможно, создать контроллер приборной панели), обеспечивают переменный экземпляр @teams
, @players
и @roles
для заполнения раскрывающегося меню для каждого класса в форме создайте отношения filled_team_roles
. Вы также можете иметь дополнительные формы в каждом из других классов, где с использованием двух выпадающих списков вместо трех с третьим значением выбранный идентификатор модели класса, в контроллере которого находится форма (например, действие edit
в players_controller
, спады для team
и role
)
~/приложение/модели/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
~/приложение/модели/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
~/приложение/модели/role.rb
class Role < ApplicationRecord
has_many :filled_team_roles, dependent: :destroy
validates_uniqueness_of :name
scope :by_name_asc, -> { order(name: :asc) }
end
~/приложение/модели/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
~/дб/мигрировать/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.Р.Б.
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
~/дБ/мигрировать/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
~/дБ/мигрировать/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
~/дБ/seeds.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)
Вопрос и комментарий: Как вы его настроили на данный момент, игрок может принадлежать нескольким командам. Так вы этого хотите? Если это так, поскольку игрок может также иметь несколько ролей, вам понадобится способ определить, в какой команде у игрока есть определенная роль. То, что приходит на ум, - это вложение атрибутов Role в Team и только создание роли в контексте команды. Я считаю, что если игрок может принадлежать только одной команде, то ваше решение немного более прямолинейно. – eggroll
Но в этом дизайне игрок может принадлежать многим командам через ': team_players'. Например: 'Team A' выдает« Player 1' 'Team B', он по-прежнему принадлежит команде« A », но статус или роль изменились. – ln9187