Here's a picture I made which visually describes the relationship I'm seeking:
In the picture I say Interaction
, but more specifically these interactions are in-game Kills. A kill, as we all know, has the killer, and the victim. In this case our killer will be called player
, and our victim will be called victim
.
Given this picture, here are some example queries I'd like to perform:
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
> []
I've tried a lot of different associations (I've been digging through google and Stack Overflow results for hours)
This is how I think my Interaction
model should look:
class Interaction < ActiveRecord::Base
belongs_to :player
has_one :victim, :class_name => 'Player'
end
And my Player
model:
class Player < ActiveRecord::Base
has_man :kills
end
And finally, how I think the migration should look:
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
interactions
table just needs a victim_id
column and then change the has_one
to belongs_to :victim, class_name: Player
.
This will work since an Interaction
is basically a join table of Player
to Player
.
has_one
implies that the victim (Player
in this case) would have a interaction_id
which is incorrect.
Instead an Interaction
belongs to the killer and the victim.
Setup as:
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