1

I started to work in a legacy project and if I try to find a cequel record and then convert it to yaml:

fj = FullJob.find(1)
fj.to_yaml

I'm getting a stack level too deep error. Checking deeper, there's a @record_collection instance variable defined in the cequel record, which it brings a copy of the same object and inside of this, another copy of the same and so on...:

[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, #...

The problem is, the ruby yaml parser, at some point, tries to parse all the instance variables of an object, which eventually derives in the mentioned SystemStackError.
Worth to mention this is only happening in this specific model, I mean, as far as I've seen, the @record_collection variable comes nil for another cequel models present in this project.
Not sure at all how this works, if this is a cequel bug or something not properly configured in the model, but... maybe has to do with cequel lazy loading?, anyway I'm running out of ideas here :(

4

1 回答 1

1

值得一提的是,这只发生在这个特定的模型中

其实不是。我认为它会发生在任何先被懒惰地实例化为“卸载”然后再加载的记录上——@record_collection即使在加载后它仍然存在(至少,我以这种方式轻松地重现了同样的故障)。

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

def cequel_to_yaml(record)
  record.load unless record.loaded?
  record.instance_variable_set(:@record_collection, nil)
  record.to_yaml
end
于 2019-03-08T13:06:16.940 回答