我有一个包含 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
应该返回新创建的 Fight
b.fights
也应该返回新创建的 Fight
到目前为止,只有 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
但是从 Fight 调用另一个模型似乎不太正确。
我还尝试在 Fighter
中重载 has_man :fights
以便它采用 lambda
has_many :fights, -> { where("fighter_id = ? OR attendee_id = ?", self.id, self.id)
但我不断收到错误 - 参数数量错误(0 为 2)
经过一番研究,我知道我应该使用双向自引用关联,类似于:Bidirectional self referential associations
但是当按照这个操作时,我会在表 Fight
中收到两条战斗记录。一个与一名战斗机相关,另一个与第二名战斗机相关。
我希望得到有关如何解决此问题的帮助或一些提示
最佳答案
如果您不想定义反向关系(如 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
关于ruby-on-rails - 双向 self 参照关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35641668/