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

Joh*_*hir 11 ruby ruby-on-rails actionview cache-digests

我有两个相互引用的部分.当我在控制台中计算嵌套依赖项时就这样(使用一些调试代码输出正在加载的模板):

finder = ApplicationController.new.lookup_context
ActionView::Digestor.new(name: "posts/show", finder: finder).nested_dependencies
Run Code Online (Sandbox Code Playgroud)

或通过像这样的rake任务:

rake cache_digests:nested_dependencies TEMPLATE=posts/show
Run Code Online (Sandbox Code Playgroud)

我得到一个初始依赖项的简短列表,然后在无限循环中,直到ruby堆栈已满:

...
>>>>>>> users/foo
>>>>>>> users/bar
>>>>>>> users/baz
>>>>>>> users/bip
>>>>>>> users/foo
>>>>>>> users/bar
>>>>>>> users/baz
>>>>>>> users/bip
SystemStackError: stack level too deep
Run Code Online (Sandbox Code Playgroud)

(模板名称已更改)

但是,当我运行应用服务器并请求模板时,事情运行得很好,没有无限循环.

以下是所有上述情况中的设置:

config.action_controller.perform_caching = true
config.cache_store = :file_store, Rails.root.to_s + '/tmp/cache/stuff'
ActionView::Base.cache_template_loading = true
Run Code Online (Sandbox Code Playgroud)

代码表明它确实具有递归参考保护: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)

nem*_*esv 1

Rails 和 rake 任务使用两种完全不同的方法ActionView::Digestor

  • Rails通常调用ActionView::Digestor.digest哪个调用compute_and_store_digest哪个就具有无限循环保护。

  • 但是nested_dependencies,仅递归DependencyTracker.find调用 _dependency,而没有任何无限循环检测。

如果你检查github 上的用法nested_dependencies,你会发现它仅在 rake 任务中使用,而没有在其他地方使用。

所以恕我直言,这是一个错误nested_dependencies