在这种情况下如何避免双重渲染?
How can I avoid double render in this situation?
我的控制器中的这段代码有问题:
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
,因为两次救援最终都会被触发。我正在寻找一个快速调整,以避免在另一个错误已经发生时触发专家,或者这个问题的替代解决方案。
是否还有其他错误 class 可以用来避免过度依赖 StandardError
?
我尝试过的东西
- 渲染后添加return
它不起作用。我认为救援链会干扰正常的
render :x and return
行为。
非常感谢!
您实际上不需要 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
一个简单的快速修复方法是在渲染后使用 return
。这样接下来就不会 运行 了。因此,在最后的所有方法中,只需使用 return
:
例如:
def user_not_authorized(exception)
render json: {
error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
}, status: :unauthorized
return
end
我的控制器中的这段代码有问题:
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
,因为两次救援最终都会被触发。我正在寻找一个快速调整,以避免在另一个错误已经发生时触发专家,或者这个问题的替代解决方案。
是否还有其他错误 class 可以用来避免过度依赖 StandardError
?
我尝试过的东西
- 渲染后添加return
它不起作用。我认为救援链会干扰正常的
render :x and return
行为。
非常感谢!
您实际上不需要 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
一个简单的快速修复方法是在渲染后使用 return
。这样接下来就不会 运行 了。因此,在最后的所有方法中,只需使用 return
:
例如:
def user_not_authorized(exception)
render json: {
error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
}, status: :unauthorized
return
end