2013-02-12 70 views
1

我在为活动记录关联进行布线时经常遇到问题,我期待着最终了解是什么导致了它(而不仅仅是解决它)。为什么我需要重新加载这个儿童关联?

当通过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 

感谢您的帮助。

回答

1

简短的答案是对象是在第一个规格和第二个不同。

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

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

虽然这两个对象是指相同的记录,它们是不同的。您已更改b.tasks[0],但t保持不变直到重新加载。

在第二规格只有对象:

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

所以t任何更新将在b.tasks[0]反映,并反之亦然。

1

它与您的操作顺序有关。

在第一次测试中,您可以拨打Task.createcreate取参数并保存到数据库并返回保存后的结果。它对批次的引用不一定是您在测试范围内处理的同一批次。

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

相关问题