SystemStackError пытается вызвать `.to_yaml` в объекте сиквела - PullRequest
1 голос
/ 08 марта 2019

Я начал работать в устаревшем проекте, и если я пытаюсь найти запись сиквела, а затем преобразовать ее в yaml:

fj = FullJob.find(1)
fj.to_yaml

Я получаю stack level too deep ошибку. Если проверить глубже, в записи сиквела определена @record_collection переменная экземпляра, определенная , которая приносит копию того же объекта, а внутри него - еще одну копию того же самого и так далее ...:

[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 пытается проанализировать все переменные экземпляра объекта, которые в конечном итоге получаются в упомянутом SystemStackError.
Стоит отметить, что это происходит только в этой конкретной модели, я имею в виду, насколько я видел, переменная @record_collection приходит nil для других моделей сиквелов, представленных в этом проекте.
Совершенно не уверен, как это работает, если это ошибка сиквела или что-то не правильно настроенное в модели, но ... может быть, это связано с ленивой загрузкой сиквела? В любом случае, у меня заканчиваются идеи: (

1 Ответ

1 голос
/ 08 марта 2019

Стоит отметить, что это происходит только в этой конкретной модели

На самом деле это не так. Я думаю, что это происходит с любой записью, которую лениво создавали как "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
...