我们正在升级旧的 Rails 4 应用程序。我们目前正在尝试从 Rails 4.2 跳转到 5.0。其中一部分涉及将 Devise 从版本 3 升级到版本 4。我们在版本 4 中一直跳得很晚,因为它应该与 Rails 5 兼容,至少根据文档和railsbump.org
到目前为止,捆绑包安装成功并且服务器启动,但是访问任何页面都会导致设备出现一些错误,我们很难弄清楚:
Error during failsafe response: Devise could not find the `Warden::Proxy` instance on your request environment.
Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack.
If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.
/home/josh/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/devise-4.9.2/lib/devise/controllers/helpers.rb:143:in `warden'
/home/josh/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/devise-4.9.2/lib/devise/controllers/helpers.rb:126:in `current_user'
/home/josh/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/paper_trail-4.0.2/lib/paper_trail/frameworks/rails/controller.rb:19:in `user_for_paper_trail'
/home/josh/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/paper_trail-4.0.2/lib/paper_trail/frameworks/rails/controller.rb:65:in `set_paper_trail_whodunnit'
从堆栈跟踪中,我们可以看到 current_user 正在从一些我们无法控制的 paper_trail 代码中调用。我们可以重写 ApplicationController 中有问题的 paper_trail 用户方法并控制那里发生的情况。这允许我们控制 current_user 和 user_signed_in 的所有实例? 。如果我们将所有这些注释掉,以便不使用这些方法,则不会出现错误并且页面将加载。至少,这可以让我们在其他一些事情上取得进展,但显然,如果应用程序要正常运行,我们需要这些助手来工作。
错误消息提到了测试,通过谷歌、ChatGPT 等围绕这个问题进行的大量研究也提到了测试。但在测试环境中并没有发生这种情况,我们相信这不是问题所在。
Warden::Manager 中间件也存在于应用程序的中间件堆栈中。
本期提出了一些有趣的想法。我们的应用程序使用自定义异常应用程序,但与提出该问题的用户不同,该应用程序不继承自 ApplicationController。注释掉这段代码并不能解决问题。不过,这是自定义异常的代码,以防万一有人注意到其中的某些内容:
def call(env)
status = env["PATH_INFO"][1..-1]
if status == "404" || status == '422' || status == '500'
Rails.application.routes.call(env)
else
super
end
end
end```
我们解决了这个问题。事实证明,Web 控制台中间件存在错误,我们只需要将 Web 控制台的版本向前推进一些即可。该错误消息非常令人困惑,因为某些事情发生在日志记录、Web 控制台和 devise/warden 之间的中间件中的顺序