2016-02-26 47 views
2

我有一个简单的数据库有2款:双向自我指涉协会

class Fighter < ActiveRecrod::Base 
    has_many :fights 
    has_many :opponents, through :fights 
end 

class Fight < ActiveRecord::Base 
    belongs_to :fighter 
    belongs_to :opponent, class_name: 'Fighter' 
end` 

我应该怎么添加这个工作:

a = Fighter.create 
b = Fighter.create 
a.opponents << b 
b.fights <- should return a value` 

a.fights应该返回新创建的战

b.fights应该返回新创建的扑灭以及

so迄今为止,只有a.fights返回值

,我想出了这样的想法:

class Fight < ActiveRecord::Base 
    belongs_to :fighter 
    belongs_to :opponent, class_name: 'Fighter' 
    after_create :create_association 

    def create_association 
    Fighter.find(opponent_id).fights << self 
    end 
end 

但调用从再战模型看起来不正确。

我也尝试过载has_man :fightsFighter因此,它需要拉姆达

has_many :fights, -> { where("fighter_id = ? OR opponent_id = ?", self.id, self.id) 但我不断得到错误 - 错误的参数数目(0 2)

研究了一下后,我知道我应该使用一个双向的自我参照关联,类似于这样的:Bidirectional self referential associations

但是当按照这个,然后我收到表Fight中的两个战斗记录。一个与一个战斗机相关,另一个与第二个战斗机相关。

我将不胜感激帮助或如何解决这个问题

+0

可以还包括你试图跟你联系的帖子?这将有助于了解可能会出现什么问题。 – Damon

回答

2

一些提示,如果你不想定义逆的关系(如this Railscast建议),我不认为你能避免每次创建两个打架时间。您使用after_create会工作的想法,只是你需要添加的对手,而不是自己打,像这样:

class Fight < ActiveRecord::Base 
    belongs_to :fighter 
    belongs_to :opponent, class_name: 'Fighter' 

    after_create :create_association 

    def create_association 
    opponent = Fighter.find(opponent_id) 
    unless opponent.opponents.include?(fighter) 
     Fighter.find(opponent_id).opponents << fighter 
    end 
    end 
end 

反向关系将在性能和存储方面更好,但不是无缝的使用方法:

class Fighter < ActiveRecord::Base 
    has_many :fights 
    has_many :opponents, through: :fights 

    has_many :inverse_fights, :class_name => "Fight", :foreign_key => "opponent_id" 
    has_many :inverse_opponents, :through => :inverse_fights, :source => :fighter 
end 

从这里,如果你想为一个战士所有对手,你应该做的a_fighter.opponents + a_fighter.inverse_opponents

+0

它的工作原理!反向关系适用于我的情况。感谢帮助。标记为答案 – beniutek