我不想在 Rails API 中发送堆栈跟踪错误
I don't want to send stack trace errors in Rails API
我正在构建 Rails 5 API 并尝试处理未找到记录时的错误响应(即 /v1/users/99
但该用户不存在)。
我正在使用 Active Model Serializer 进行序列化,我认为必须有一种方法可以只显示状态和错误,而不是堆栈跟踪。现在,我明白了:
{
status: 404,
error: "Not Found",
exception: "#<ActiveRecord::RecordNotFound: Couldn't find User with 'id'=99>",
traces: {
Application Trace: [
{
id: 1,
trace: "app/controllers/api/v1/users_controller.rb:45:in `set_user'"
}
],
Framework Trace: [
{
id: 0,
trace: "activerecord (5.0.2) lib/active_record/core.rb:173:in `find'"
},
{
id: 2,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:382:in `block in make_lambda'"
},
{
id: 3,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional'"
},
{
id: 4,
trace: "actionpack (5.0.2) lib/abstract_controller/callbacks.rb:12:in `block (2 levels) in <module:Callbacks>'"
},
{
id: 5,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'"
},
.
.
.
我希望 API 端的错误简单一些,只有状态和错误。如何做到这一点?
begin
user = User.find(params[:id])
rescue
render json: 'no user found', status: 404
end
render json: user, status: 200
或者您可以使用通用处理程序处理所有控制器中的异常
class ApiController < ApplicationController
around_action :handle_exceptions
def handle_exceptions
begin
yield
rescue ActiveRecord::RecordNotFound => e
status = 404
rescue ActiveRecord::RecordInvalid => e
status = 403
rescue Exception => e
status = 500
end
handle_error "#{e.message}", status unless e.class == NilClass
end
def handle_error(message, status = 500)
message = message.is_a?(Array) ? message.join('. ') : message
@errors = { message: message, status: status }
render json: @errors, :status => status
end
end
In your controller no need to write rescue, Just find the record
user = User.find(params[:id])
我一直这样做是为了在不同的环境中记录和打印不同的消息。
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found_rescue
def record_not_found_rescue(exception)
logger.info("#{exception.class}: " + exception.message)
if Rails.env.production?
render json: {}, status: :not_found
else
render json: { message: exception, backtrace: exception.backtrace }, status: :not_found
end
end
end
我发现这不仅对不回显跟踪很有用,而且您现在不需要在每个控制器操作中都使用 if 语句。
它与控制器中的查找器方法结合得很好。
def show
user = find_user
render json: user , status: :ok
end
private
def find_user
User.find(params[:id])
end
请记住,您可以像这样处理不同类型的异常,而不仅仅是 ActiveRecord::RecordNotFound
。
我正在构建 Rails 5 API 并尝试处理未找到记录时的错误响应(即 /v1/users/99
但该用户不存在)。
我正在使用 Active Model Serializer 进行序列化,我认为必须有一种方法可以只显示状态和错误,而不是堆栈跟踪。现在,我明白了:
{
status: 404,
error: "Not Found",
exception: "#<ActiveRecord::RecordNotFound: Couldn't find User with 'id'=99>",
traces: {
Application Trace: [
{
id: 1,
trace: "app/controllers/api/v1/users_controller.rb:45:in `set_user'"
}
],
Framework Trace: [
{
id: 0,
trace: "activerecord (5.0.2) lib/active_record/core.rb:173:in `find'"
},
{
id: 2,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:382:in `block in make_lambda'"
},
{
id: 3,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional'"
},
{
id: 4,
trace: "actionpack (5.0.2) lib/abstract_controller/callbacks.rb:12:in `block (2 levels) in <module:Callbacks>'"
},
{
id: 5,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'"
},
.
.
.
我希望 API 端的错误简单一些,只有状态和错误。如何做到这一点?
begin
user = User.find(params[:id])
rescue
render json: 'no user found', status: 404
end
render json: user, status: 200
或者您可以使用通用处理程序处理所有控制器中的异常
class ApiController < ApplicationController
around_action :handle_exceptions
def handle_exceptions
begin
yield
rescue ActiveRecord::RecordNotFound => e
status = 404
rescue ActiveRecord::RecordInvalid => e
status = 403
rescue Exception => e
status = 500
end
handle_error "#{e.message}", status unless e.class == NilClass
end
def handle_error(message, status = 500)
message = message.is_a?(Array) ? message.join('. ') : message
@errors = { message: message, status: status }
render json: @errors, :status => status
end
end
In your controller no need to write rescue, Just find the record
user = User.find(params[:id])
我一直这样做是为了在不同的环境中记录和打印不同的消息。
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found_rescue
def record_not_found_rescue(exception)
logger.info("#{exception.class}: " + exception.message)
if Rails.env.production?
render json: {}, status: :not_found
else
render json: { message: exception, backtrace: exception.backtrace }, status: :not_found
end
end
end
我发现这不仅对不回显跟踪很有用,而且您现在不需要在每个控制器操作中都使用 if 语句。
它与控制器中的查找器方法结合得很好。
def show
user = find_user
render json: user , status: :ok
end
private
def find_user
User.find(params[:id])
end
请记住,您可以像这样处理不同类型的异常,而不仅仅是 ActiveRecord::RecordNotFound
。