我不想在Rails API中发送堆栈跟踪错误

时间:2017-03-28 07:24:25

标签: ruby-on-rails active-model-serializers 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方面的错误很简单,只需要状态和错误。怎么办呢?

2 个答案:

答案 0 :(得分:2)

我一直这样做是为了在不同的环境中记录和打印不同的消息。

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语句。

它与您控制器中的finder方法很好地结合。

  def show
    user = find_user

    render json: user , status: :ok
  end

  private
    def find_user
      User.find(params[:id])
    end

请记住,您可以处理不同类型的此类异常,而不仅仅是ActiveRecord::RecordNotFound

答案 1 :(得分:1)

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])