是的,你可以。有时这是个好主意,但不在这里。您需要一个连接表。原因如下。
您需要使用两个不同的列名并告诉 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
如果您想要所有 Player 的结果怎么办?如果你想要一个结果的所有玩家怎么办?有问题。您需要进行冗余查询或添加额外的子句,例如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,请将其添加到具有唯一约束的 Result 表中。
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)