即使解决了这个问题,我也只是想插话,并报告我是如何解决这个问题的。我有与 OP 相同的症状,初始请求 .id() 工作正常,后续请求 .id() 会抛出“堆栈太深”错误消息。这是一个奇怪的错误,因为它通常意味着你在某处有一个无限循环。我通过更改解决了这个问题:
config.action_controller.perform_caching = true
config.cache_classes = false
到
config.action_controller.perform_caching = true
config.cache_classes = true
在环境/production.rb 中。
更新:这个问题的根本原因原来是cache_store。默认的 MemoryStore 不会保留 ActiveRecord 模型。这是一个相当古老的错误,而且相当严重,我不知道为什么它没有被修复。无论如何,解决方法是使用不同的 cache_store。尝试在您的 config/environments/development.rb 中使用它:
config.cache_store = :file_store
更新#2:C. Bedard 发布了对这个问题的分析。似乎总结得很好。
我自己遇到了这个问题(并且反复被卡住)我已经调查了这个错误(并希望找到一个很好的解决方法)。这是我所知道的:它发生在 ActiveRecord::Base#reset_subclasses 在请求之间由调度程序调用时(仅在开发模式下)。
ActiveRecord::Base#reset_subclasses 清除了inheritable_attributes 哈希(存储#skip_time_zone_conversion_for_attributes 的位置)。它不仅会发生在通过请求持久化的对象上,正如 #1290 中的“猴子测试应用程序”所示,而且在尝试访问 AR 上生成的关联方法时也会发生,即使对于仅存在于当前请求的对象也是如此。
此提交引入了此错误,其中 #skip_time_zone_conversion_for_attributes 声明从 base.cattr_accessor 更改为 base.class_inheritable_accessor。但话又说回来,同样的提交也修复了其他问题。最初在这里提交的补丁只是避免清除 reset_subclasses 中的 instance_variables 和 instance_methods 确实会引入大量泄漏,并且泄漏的数量似乎与应用程序的复杂性成正比(即每个模型、关联和属性的数量)。我有一个非常复杂的应用程序,当应用补丁时,它在开发模式下的每个请求都会泄漏近 1Mb。所以它不可行(无论如何对我来说)。
在尝试不同的方法来解决这个问题时,我已经纠正了最初的错误(skip_time_zone_conversion_for_attributes 在第二次请求中为 nil),但它发现了另一个错误(这只是没有发生,因为在到达它之前会引发第一个异常)。该错误似乎是 #774 中报告的错误(“id”方法的 method_missing 中的堆栈溢出)。
现在,对于解决方案,我的补丁(附加)执行以下操作:它为#skip_time_zone_conversion_for_attributes 方法添加了包装器方法,确保它始终将值作为class_inheritable_attribute 读取/写入。这样,nil 就不再返回了。
它确保在调用 reset_subclasses 时不会清除 'id' 方法。AR 在那个方面有点奇怪,因为它首先直接在源代码中定义它,但在第一次调用时使用 #define_read_method 重新定义自己。这正是它在重新加载后失败的原因(因为 reset_subclasses 然后将其清除)。
我还在 reload_models_test.rb 中添加了一个测试,它调用 reset_subclasses 来尝试在开发模式下模拟请求之间的重新加载。在这一点上我不能说的是它是否真的像在实时调度程序请求周期中那样触发重新加载机制。我还从脚本/服务器进行了测试,错误消失了。
抱歉,粘贴太长了,rails 灯塔项目是私有的,这很糟糕。上面提到的补丁是私有的。