Rails,使用belongs_to和has_one关联到同一个类

时间:2017-10-31 16:44:09

标签: ruby activerecord sinatra sinatra-activerecord

这是我制作的一张图片,它直观地描述了我寻求的关系:enter image description here

在图片中我说Interaction,但更具体地说,这些互动是游戏中的杀戮。众所周知,杀戮有杀手和受害者。在这种情况下,我们的杀手将被称为player,我们的受害者将被称为victim

鉴于此图片,以下是我想要执行的一些示例查询:

Player.find(1).Interactions
> [<#Interaction id: 1>, <#Interaction id: 2>, <#Interaction id: 3>]

Interactions.where(player: Player.find(1))
> [<#Interaction id: 1>, <#Interaction id: 2>, <#Interaction id: 3>]

Interactions.where(victim: Player.find(1))
> [<#Interaction id: 4>]

Player.find(1).Interactions.where(victim: Player.find(2))
> [<#Interaction id: 2>]

Player.find(1).Interactions.count()
> 3

# Player.find(1).Interactions should (ideally) return Interactions where <#Player id: 1> is the player (not victim)

Interactions.all.count()
> 4

Player.all.count()
> 4

Player.find(2).Interactions
> []

Player.find(3).Interactions
> [ <#Interaction id: 4> ]

Player.find(4).Interactions
> []

我尝试了很多不同的关联(我已经挖掘了谷歌和Stack Overflow数据数小时)

我认为我的Interaction模型看起来应该是这样的:

class Interaction < ActiveRecord::Base
  belongs_to :player
  has_one :victim, :class_name => 'Player'
end

我的Player型号:

class Player < ActiveRecord::Base
  has_man :kills
end

最后,我认为迁移应该如何看待:

class CreatePlayerAndInteraction < ActiveRecord::Migration[5.0]
  def change
    create_table :players do |t|
      t.string :steam_id
    end

    create_table :interactions do |t|
      t.string :weapon
      t.belongs_to :player, index: true
    end
end

2 个答案:

答案 0 :(得分:1)

EACCES表只需要interactions列,然后将victim_id更改为has_one

这将有效,因为belongs_to :victim, class_name: Player基本上是InteractionPlayer的联接表。

Player表示受害者(在这种情况下为has_one)的Player不正确。

相反,interaction_id属于杀手和受害者。

设置为:

Interaction

答案 1 :(得分:0)

engineermnky给了我一个很好的答案,帮助我解决了这个问题,但它有点松懈。这是我用来解决问题的确切解决方案:

# ./models/player.rb
class Player < ActiveRecord::Base
  has_many :interactions
end

# ./models/interaction.rb
class Interaction < ActiveRecord::Base
  belongs_to :player
  belongs_to :victim, class_name: 'Player', foreign_key: 'victim_id'
end

# ./db/migrate/migrate/create_players.rb
class CreatePlayersAndInteractions < ActiveRecord::Migration[5.0]
  def change
    create_table :interactions do |t|
      t.integer :victim_id
      t.belongs_to :player, index: true
    end
  end
end