我的父类有时没有在孩子的after_save
回调中加载所有孩子。
我有两种模式:
class Parent < ActiveRecord::Base
has_many :children
def update_something
# explained below
end
end
class Child < ActiveRecord::Base
belongs_to :parent
after_save :tell_parent_to_update
def tell_parent_to_update
parent.update_something
end
end
我有一个测试我正在运行它,它只检查了两件事。 parent.children.count
和parent.children.length
。 两者都应该是4。我意识到计数有时会有所不同,但(据我所知)它不应该在这里。
如果我定义update_something
只是迭代children
:
def update_something
children.each do |child|
end
end
测试失败 - 循环将执行一次(并将返回单个孩子的数组 - 第一个 child
已创建)。
否则,我可以输入任何代码,只要它没有提及children
并且它可以正常工作。这就像对孩子的呼叫导致关联加载错误的东西。
强制重新加载修复它:
def update_something
children(true).each do |child|
end
end
但这很糟糕,如果可能的话,我宁愿修复root问题。
这是我的错误还是铁轨错误(如果有的话,我可以做些什么来解决这个问题)?
我怀疑这很重要,但这是一个使用sqlite3的测试环境。虽然如果我在单个开发控制台会话中创建和测试记录,它也会在开发环境中失败。
答案 0 :(得分:3)
在黑暗中刺,但你可能需要inverse_of
,我认为相关的对象存储在同一个内存块中,而不是标准方法会创建的不同块:
#app/models/parent.rb
class Parent < ActiveRecord::Base
has_many :children, inverse_of: :parent
...
end
#app/models/child.rb
class Child < ActiveRecord::Base
belongs_to :parent, inverse_of: :children
...
end
根据我自己的经验,我发现inverse_of
允许您调用其他模型中的关联数据。例如,在没有 parent.update_something
的情况下调用inverse_of
会导致错误(如果未明确定义parent
),或者必须构建{{1再次提出对象。
-
如果没有帮助,我会删除答案。
答案 1 :(得分:0)
这可能是因为在运行tell_parent_to_update之前,父代的子元素已经在代码中的某个位置急切加载。
parent.children.count将运行SQL查询并返回数据库中存在的子项数,而parent.children.length将返回子数组的长度(可能已经急于加载)。
我建议您手动尝试从rails控制台保存1个子对象,并查看update_something中子项的长度和计数是否相同。如果是,那么您的测试可能因为之前的某些代码而失败。