我有两个相互引用的部分.当我在控制台中计算嵌套依赖项时就这样(使用一些调试代码输出正在加载的模板):
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)
根据我对Rails中俄罗斯娃娃缓存的理解,当我们进行RDC(俄罗斯娃娃缓存)时,这对于急切的加载相关对象或对象列表是有害的,因为在RDC中我们只是从数据库加载顶级对象,并查找它缓存渲染的模板和服务.如果我们要急切加载相关的对象列表,如果缓存不是陈旧的话,这将是无用的.
我的理解是否正确?如果是,我们如何确保我们在第一次调用时急切加载所有相关对象,以免在第一次加载(缓存不热)时支付N + 1个查询的成本.
caching ruby-on-rails ruby-on-rails-3 russian-doll-caching cache-digests