SystemStackError尝试在续集对象中调用`.to_yaml`

时间:2019-03-08 03:53:57

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

我开始在一个遗留项目中工作,如果我尝试查找续集记录,然后将其转换为yaml:

fj = FullJob.find(1)
fj.to_yaml

我遇到一个stack level too deep错误。 更深入地检查,有一个@record_collection实例变量,定义为in the cequel record,它带来相同对象的副本,并在其内部,相同对象的另一个副本,依此类推……:

[7] pry(main)> fj.instance_variables
=> [:@record_collection, :@cequel_attributes, :@collection_proxies, :@loaded, :@persisted]
[8] pry(main)> fj.instance_variable_get(:@record_collection)
=> [#<FullJob id: 1, #...
[9] pry(main)> fj.instance_variable_get(:@record_collection).first.instance_variable_get(:@record_collection)
=> [#<FullJob id: 1, #...

问题是,ruby yaml解析器有时会尝试解析all the instance variables的对象,该对象最终会在提到的SystemStackError中派生。
值得一提的是,这种情况仅在此特定模型中才会发生,我的意思是,据我所知,此项目中存在的另一个续集模型的变量@record_collection来自nil
根本不知道它是如何工作的,如果这是一个cequel错误或在模型中未正确配置的东西,但是...可能与cequel延迟加载有关吗?无论如何,我在这里的想法已不多了:(

1 个答案:

答案 0 :(得分:1)

  

值得一提的是,这种情况仅在此特定模型中发生

实际上不是。我认为它会发生在首先是lazily instantiated as "unloaded"然后又是后来加载的任何记录上-即使加载后它的@record_collection仍会停留在那里(至少,我很容易地以这种方式重现了同样的故障)。

我无法在cequel源代码中找到任何放置它们的实例变量值的位置(肯定不会在加载时发生)。另一方面,除了此延迟加载行为外,似乎没有在其他任何地方使用此值(因此,在记录加载后有点“无用”),因此使用像猴子这样的丑陋的补丁解决方法助手可能是安全的

def cequel_to_yaml(record)
  record.load unless record.loaded?
  record.instance_variable_set(:@record_collection, nil)
  record.to_yaml
end