Да, вы можете. И иногда это хорошая идея, но не здесь. Вы хотите объединить таблицу вместо этого. И вот почему.
Вам нужно использовать два разных имени столбца и сообщить Rails, на какую таблицу они ссылаются.
Result
t.string :name1
t.integer :goal1
t.string :name2
t.integer :goal2
t.datetime :date
t.references :player1,
null: false,
foreign_key: { to_table: :players }
t.references :player2,
null: false,
foreign_key: { to_table: :players }
И вам нужно сделать их явными в вашем коде.
class Result < ApplicationRecord
belongs_to :player1, class_name: 'Player'
belongs_to :player2, class_name: 'Player'
end
Связать их вместе в Player - маленький обманщик. Наивное, что нужно сделать, это:
class Player < ApplicationRecord
has_many :player1_results,
class_name: 'Result',
foreign_key: :player1_id
has_many :player2_results,
class_name: 'Result',
foreign_key: :player2_id
end
Что если вы хотите получить все результаты игрока? Что делать, если вы хотите, чтобы все игроки в результате? В этом проблема. Вам нужно сделать лишние запросы или добавить дополнительные предложения, такие как where player1_id = :player_id or player2_id = :player_id
. Точно так же name1
, name2
, goal1
, goal2
.
Если вы хотите сохранить более одной связанной вещи, вам нужна таблица соединений. Даже если это только два. Это делает жизнь намного проще.
У вас есть таблица результатов, но результат чего? Матч! Где хранится информация о матче? В таблице результатов. Это должна быть собственная таблица.
У нас есть три таблицы. Игроки, матчи и стол для хранения результатов, полученных игроком в матче (результат).
create_table :players do
t.string :name, null: fase
...
t.timestamps
end
create_table :matches do
t.string :name, null: false
t.datetime :date, null: false
...
t.timestamps
end
create_table :results do
t.references :player, foreign_key: true, null: false
t.references :match, foreign_key: true, null: false
t.integer :goals
end
Теперь со всеми тремя фигурами мы можем собрать их вместе. Матчи и игроки связаны с до Результаты.
class Matches < ApplicationRecord
has_many :results
has_many :players, through: :results
end
class Players < ApplicationRecord
has_many :results
has_many :matches, through: :results
end
class Results < ApplicationRecord
belongs_to :match
belongs_to :player
end
Теперь, если вы хотите найти игроков в вашем матче ...
players = match.players
Это будет выполнено объединение результатов для вас.
Если вам необходимо отследить, кто является игроком 1 и игроком 2, добавьте это в таблицу результатов с уникальным ограничением.
create_table :results do
t.references :player, foreign_key: true, null: false
t.references :match, foreign_key: true, null: false
t.integer :goals, null: false, default: 0
t.integer :player_number, null: false, default 1
# Can't have two player 1s for the same match.
# :player_number is deliberately first so this index also serves
# to index player_number.
t.index [:player_number, :match_id], unique: true
end
Тогда вы можете получить игрока 1 вот так:
player = match.players.find_by!(player_number: 1)
И вы можете добавить несколько удобных методов в отношения.
class Matches < ApplicationRecord
has_many :results
has_many :players, through: :results do
def player(num)
match.players.find_by!(player_number: num)
end
end
end
player = match.players.player(1)