首页 > 解决方案 > 在这种情况下如何避免双重渲染?

问题描述

我的控制器中的这段代码有问题:

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根源。这个控制器工作得很好,当权威错误是唯一发生的错误时,它可以从权威白名单检查中解救出来。

但是,只要与权威人士一起发生任何其他错误,我就会得到一个,DoubleRenderError因为两个救援最终都被触发了。我正在寻找一个快速调整,以避免专家在另一个错误已经发生时触发,或者这个问题的替代解决方案。

是否有任何其他错误类可以用来避免过度依赖StandardError

我尝试过的事情

非常感谢!

标签: ruby-on-railsapicontrollerpunditrescue

解决方案


你真的不需要,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

https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/public_exceptions.rb#L14


推荐阅读