Rails关联未正确加载

时间:2015-12-27 05:53:21

标签: ruby-on-rails ruby ruby-on-rails-4

我的父类有时没有在孩子的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.countparent.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的测试环境。虽然如果我在单个开发控制台会话中创建和测试记录,它也会在开发环境中失败。

2 个答案:

答案 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再次提出对象。

good write-up here

-

如果没有帮助,我会删除答案。

答案 1 :(得分:0)

这可能是因为在运行tell_parent_to_update之前,父代的子元素已经在代码中的某个位置急切加载。

parent.children.count将运行SQL查询并返回数据库中存在的子项数,而parent.children.length将返回子数组的长度(可能已经急于加载)。

我建议您手动尝试从rails控制台保存1个子对象,并查看update_something中子项的长度和计数是否相同。如果是,那么您的测试可能因为之前的某些代码而失败。