【问题标题】:Rails, using a belongs_to and has_one association to the same classRails,对同一个类使用 belongs_to 和 has_one 关联
【发布时间】:2017-10-31 16:44:08
【问题描述】:

这是我制作的一张图片,它直观地描述了我正在寻找的关系:

在图片中我说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

【问题讨论】:

  • 嘿!就这么简单,谢谢。如果您做出回答,我很乐意接受。

标签: ruby activerecord sinatra sinatra-activerecord


【解决方案1】:

interactions 表只需要一个victim_id 列,然后将has_one 更改为belongs_to :victim, class_name: Player

这将起作用,因为Interaction 基本上是PlayerPlayer 的连接表。

has_one 暗示受害者(在这种情况下为Player)将拥有一个不正确的interaction_id

相反,Interaction 属于凶手和受害者。

设置为:

class Player
  has_many :kills, class_name: Interaction, foreign_key: :player_id inverse_of: :killer
  has_many :deaths, class_name: Interaction, foreign_key: :victim_id, inverse_of: :victim 
end

class Interaction
  belongs_to :killer, class_name: Player, foreign_key: :player_id, inverse_of: :kills
  belongs_to :victim, class_name: Player, foreign_key: :victim_id, inverse_of :deaths
end

【讨论】:

    【解决方案2】:

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

    # ./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
    

    【讨论】:

    • Interaction 更改为 Kill 或者这没有任何意义,而且我的“绒毛”现在是基于此的功能 Player 有杀戮但没有死亡
    • @engineersmnky 感谢您指出这一点!我修好了它。我说有一些绒毛的原因是因为死亡不一定与杀戮相反。玩家可以通过其他方式死亡。我想确保对这个问题有一个清晰、准系统的答案。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2014-05-05
    相关资源
    最近更新 更多