2

在连接活动记录关联时,我经常遇到问题,我希望最终了解导致它的原因(而不是仅仅解决它)。

当通过 parent.children<< 将孩子与父母相关联时,对孩子的引用会正确更新自己。如果反向建立关系(如果通过 child.parent= 完成),这将不一样。

为什么会这样?有没有办法使关系双向?

我过去尝试过inverse_of,但没有成功。我希望是因为我对这里发生的事情还不够了解。

例子:

鉴于这些模型:

class Task < ActiveRecord::Base
  belongs_to :batch

  attr_accessor :state
end

class Batch < ActiveRecord::Base
  has_many :tasks

  def change_tasks
     tasks.each { |x| x.state = "started" }
  end
end

为什么第一个规范失败但第二个通过?我可以通过第一关吗?出于某种原因,我需要在第一个规范中重新加载,而不是在第二个规范中。

describe "avoiding reload" do

  context "when association established via child.parent=" do
    it "updates child references" do
      b = Batch.create
      t = Task.create(batch: b)

      b.change_tasks

      b.tasks[0].state.should == "started" # passes
      t.state.should == "started" # fails!?
      t.reload.state.should == "started" # passes, note the reload
    end
  end

  context "when association established via parent.children<<" do
    it "updates child references" do
      b = Batch.create
      t = Task.create
      b.tasks << t

      b.change_tasks

      b.tasks[0].state.should == "started" # passes
      t.state.should == "started" # passes
    end
  end

end

谢谢您的帮助。

4

2 回答 2

1

它与您的操作顺序有关。

在您调用的第一个测试Task.create中。create获取参数并保存到数据库并在保存后返回结果。它对其批次的引用不一定与您在测试范围内处理的批次相同。

在第二个测试中,您在调用 create 后分配任务。然后立即访问它。因此,相同的任务 t 是在 内change_tasks和期间的引用t.state.should == "started"

于 2013-02-12T18:25:40.163 回答
1

简短的回答是第一个规范和第二个规范中的对象不同。

在第一个规范中,您有 2 个不同的对象(尝试检查 rails 控制台):

t.object_id != b.tasks[0].object_id

虽然两个对象都引用相同的记录,但它们是不同的。您已更改b.tasks[0],但t在重新加载之前保持不变。

在第二个规范中只有对象:

t.object_id == b.tasks[0].object_id   

因此,任何更新都t将反映在 中b.tasks[0],反之亦然。

于 2013-02-12T18:41:19.100 回答