Почему мои самореферентные шаблоны разбивают вычисления кэша в консоли и грабли, но не на сервере?
У меня есть две частичные части, которые относятся друг к другу. Когда я вычисляю вложенные зависимости в консоли, так нравится (с некоторым кодом отладки, выводящим, какой шаблон загружается):
finder = ApplicationController.new.lookup_context
ActionView::Digestor.new(name: "posts/show", finder: finder).nested_dependencies
или с помощью команды rake:
rake cache_digests:nested_dependencies TEMPLATE=posts/show
Я получаю короткий список начальных зависимостей, а затем это в бесконечном цикле, пока пол ruby не будет заполнен:
...
>>>>>>> users/foo
>>>>>>> users/bar
>>>>>>> users/baz
>>>>>>> users/bip
>>>>>>> users/foo
>>>>>>> users/bar
>>>>>>> users/baz
>>>>>>> users/bip
SystemStackError: stack level too deep
(изменены имена шаблонов)
Однако, когда я запускаю сервер приложений и запрашиваю шаблон, все работает нормально, без бесконечных циклов.
Вот мои настройки во всех вышеперечисленных случаях:
config.action_controller.perform_caching = true
config.cache_store = :file_store, Rails.root.to_s + '/tmp/cache/stuff'
ActionView::Base.cache_template_loading = true
Код указывает, что он имеет рекурсивную защиту ссылок: https://github.com/rails/rails/blob/v4.1.8/actionview/lib/action_view/digestor.rb#L35
Почему эта защита работает в среде сервера, но не в консоли или задаче грабли?
(также проблема github https://github.com/rails/rails/issues/18667)
Ответы
Ответ 1
Рельсы и команда rake используют два совершенно разных метода ActionView::Digestor
.
-
Rails обычно вызывает ActionView::Digestor.digest
, который вызывает compute_and_store_digest
, который имеет бесконечную защиту цикла.
-
Однако nested_dependencies
рекурсивно вызывает DependencyTracker.find
_dependencies без какого-либо обнаружения бесконечного цикла.
Если вы проверяете использование в nested_dependencies
в github, вы можете видеть, что он используется только из задачи rake и больше нигде.
Итак, IMHO это ошибка в nested_dependencies
.