Почему мои самореферентные шаблоны разбивают вычисления кэша в консоли и грабли, но не на сервере?

У меня есть две частичные части, которые относятся друг к другу. Когда я вычисляю вложенные зависимости в консоли, так нравится (с некоторым кодом отладки, выводящим, какой шаблон загружается):

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.