我有一个包含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
也应该返回新创建的战斗
到目前为止只有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调用另一个模型似乎不对。
我还试图在has_man :fights
中重载Fighter
,以便它需要lambda
has_many :fights, -> { where("fighter_id = ? OR opponent_id = ?", self.id, self.id)
但我经常得到错误 - 错误的参数数量(0表示2)
但是当我遵循这个时,我会在表Fight
中收到两个战斗记录。一个与一个战斗机相关联,另一个与第二个战斗机相关联。
我很感激如何解决这个问题的帮助或一些提示
答案 0 :(得分:2)
如果您不想定义反向关系(如this Railscast中所述),我不认为您每次都可以避免创建两个战斗。你使用SELECT ALL fr.sku, fr.dispo, eutemp.dispo
FROM totfrhrl as fr
LEFT JOIN totrihrl_temp eutemp ON fr.sku = eutemp.sku
WHERE exists(select 1 from totfrhrl_temp frtemp
where frtemp.sku = fr.sku
and ( fr.dispo != frtemp.dispo OR fr.command != frtemp.command OR fr.eta != frtemp.eta))
Union ALL
SELECT ALL eu.sku, eu.dispo, frtemp.dispo
FROM totrihrl as eu
LEFT JOIN totfrhrl_temp frtemp ON eu.sku = frtemp.sku
WHERE exists(select 1 from totrihrl_temp eutemp
where eutemp.sku = eu.sku
and (eu.dispo != eutemp.dispo OR eu.command != eutemp.command OR eu.eta != eutemp.eta))
and not exists (select 1 from totfrhrl as fr where fr.sku=eu.sku)
的想法是有效的,只需要添加对手而不是战斗本身,就像这样:
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