为什么我的自我引用模板在控制台和rake中会破坏缓存摘要计算,但在服务器上却不会?

11

我有两个互相引用的部分。当我在控制台中计算嵌套依赖项时(使用一些调试代码输出哪个模板正在被加载),如下所示:

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

为什么这种保护在服务器环境中能够正常工作,但在控制台或rake任务中却不能?

(还有一个Github问题:https://github.com/rails/rails/issues/18667)


Rails和rake任务使用完全不同的方法。Rails调用ActionView::Digestor.digest,该方法调用compute_and_store_digest,该方法具有无限循环保护。但是,nested_dependencies仅递归调用DependencyTracker.find_dependencies,没有任何无限循环检测。如果您在github上检查nested_dependencies的用法,您会发现它只在rake任务中使用,而其他地方则没有。因此,在我看来,这是nested_dependencies中的一个错误。 - nemesv
谢谢...为什么这是一条注释? - John Bachir
1个回答

1
Rails和rake任务使用ActionView::Digestor的两种完全不同的方法。
- Rails通常调用ActionView::Digestor.digest,该方法调用compute_and_store_digest,该方法具有无限循环保护。 - 然而nested_dependencies仅递归调用DependencyTracker.find_dependencies而没有任何无限循环检测。
如果您在github上检查nested_dependencies的用法,您会发现它仅从rake任务中使用,而其他地方没有使用。
所以在我看来,这是nested_dependencies中的一个错误

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接