我的控制器中的这段代码有问题:
class Api::V1::BaseController < ActionController::API
include Pundit
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
rescue_from StandardError, with: :internal_server_error
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
rescue_from ActiveRecord::RecordNotFound, with: :not_found
private
def user_not_authorized(exception)
render json: {
error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
}, status: :unauthorized
end
def not_found(exception)
render json: { error: exception.message }, status: :not_found
end
def internal_server_error(exception)
if Rails.env.development?
response = { type: exception.class.to_s, message: exception.message, backtrace: exception.backtrace }
else
response = { error: "Internal Server Error" }
end
render json: response, status: :internal_server_error
end
end
rescue_from StandardError
是我所有麻烦的根源。当控制器错误是唯一发生的情况时,该控制器可以很好地工作并从Pundit白名单检查中恢复。
但是,一旦其他任何错误与专家一起发生,我就会得到DoubleRenderError
,因为这两种救援都最终被触发了。我正在寻找一种快速调整措施,以防止在发生另一个错误时才触发专家,或者针对此问题的替代解决方案。
还有其他错误类可以用来避免严重依赖StandardError
吗?
render :x and return
行为。非常感谢您!
答案 0 :(得分:1)
您实际上并不需要rescue_from StandardError
,因为这是Rails的默认行为。 Rails有一个名为PublicExceptions
的中间件,该中间件(主要)完成您想要的操作,因此您可以让StandardError传播。
它将代替{ error: "Internal Server Error" }
呈现
{
status: status,
error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500])
}
,如果出现异常,将呈现{ status: 500, error: "Internal Server Error" }
。这应该是一个合理的妥协。
对于开发,您可以考虑采用此中间件。您可以使用config.exceptions_app
进行设置。
https://guides.rubyonrails.org/configuring.html#rails-general-configuration
https://api.rubyonrails.org/classes/ActionDispatch/PublicExceptions.html
答案 1 :(得分:0)
一个简单的快速修复方法是在渲染后仅使用return
。这样,下一步将无法运行。因此,在最后的所有方法中,只需使用return
:
例如:
def user_not_authorized(exception)
render json: {
error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
}, status: :unauthorized
return
end