【问题标题】:I don't want to send stack trace errors in Rails API我不想在 Rails API 中发送堆栈跟踪错误
【发布时间】:2017-03-28 07:24:25
【问题描述】:

我正在构建一个 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 端的错误简单,只是状态和错误。如何做到这一点?

【问题讨论】:

    标签: ruby-on-rails active-model-serializers rails-api


    【解决方案1】:

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

    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

    【讨论】:

    • 这就是我要找的。我稍微编辑了 json 响应,只是为了显示 prod 上的状态和错误,但这样做似乎非常灵活。
    【解决方案2】:
    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])
    

    【讨论】:

    • 这当然有帮助!我想知道是否有任何东西可以保存在序列化程序中?或者也许在render json: 'no user found', status: 404 时,我可以使用 AMS 调用响应。不管怎样,很高兴知道我可以接受这个。
    • 在您的代码中,如果发生任何错误,您将面临双重渲染错误。
    • 在哪里发现双重渲染错误?仅供参考,第一部分和第二部分不同
    • 如果用户不存在于救援块一个渲染和救援块后另一个渲染。它将通过双重渲染错误
    猜你喜欢
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-23
    相关资源
    最近更新 更多