SystemStackError пытается вызвать `.to_yaml` в объекте сиквела
Я начал работать в старом проекте, и если я попытаюсь найти запись сиквела, а затем преобразовать ее в 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 ответ
Стоит отметить, что это происходит только в этой конкретной модели
На самом деле это не так. Я думаю, что это происходит с любой записью, которую сначала лениво создавали как "выгруженную", а затем загружали позже - ее @record_collection
остается там даже после загрузки (по крайней мере, я легко воспроизвел ту же ошибку).
Я не могу найти ни одного места в cequel
исходный код, где они сбрасывают значение переменной этого экземпляра (это не происходит при загрузке наверняка). С другой стороны, кажется, что это значение не используется где-либо еще, кроме этого ленивого поведения загрузки (так что оно становится "бесполезным" после загрузки записи), так что может быть безопасно использовать такой уродливый помощник по исправлению ошибок, как
def cequel_to_yaml(record)
record.load unless record.loaded?
record.instance_variable_set(:@record_collection, nil)
record.to_yaml
end