ruby-on-rails 如何在Rails中呈现自定义JSON错误响应“Couldn't find Plan with id”?

bqucvtff  于 2023-02-17  发布在  Ruby
关注(0)|答案(1)|浏览(133)

我想呈现一个自定义错误,当用户无法通过id找到类'Plan'时显示该错误。问题是它没有到达if语句。

NB.我正在使用失眠症来测试它。

class Api::V1::PlansController < Api::V1::BaseController
  before_action :authorize_request

  def show
    @plan = Plan.find(params[:id])
    if @plan.errors.any?
      render json 'wrong'
    else
      @accounts = @plan.accounts
      render json: @plan, status: :created
    end
  end

end

ryevplcw

ryevplcw1#

ActiveRecord::FinderMethods#find将在无法找到某个id时引发ActiveRecord::RecordNotFound异常。当引发异常时,它将停止执行。
您可以使用rescue_from处理异常:

# Do not use the scope resolution operator when declaring classes and modules
# @see https://github.com/rubocop-hq/ruby-style-guide#namespace-definition
module Api
  module V1
    class PlansController < BaseController
      before_action :authorize_request
      rescue_from ActiveRecord::RecordNotFound, with: :not_found

      def show
        @plan = Plan.find(params[:id])
        render json: @plan
      end

      private

      def not_found
        render json: { error: 'not found' }, status: :not_found       
      end      
    end
  end
end

使用find_by的建议最初听起来似乎是个好主意,直到您意识到异常确实很有用,因为它可以暂停操作的执行并防止nil错误。

module Api
  module V1
    class PlansController < BaseController
      # ... 
      before_action :set_plan

      def update
        # this would create a nil error if we had used 'find_by'
        if @plan.update(plan_params)
          # ...
        else
          # ...
        end
      end

      private
      def set_plan
        @plan = Plan.find(params[:id])
      end
    end
  end
end

使用rescue_from也是一个非常强大的模式,因为它允许您在继承链中向上移动错误处理,而不是重复自己的操作:

module Api
  module V1
    class BaseController < ::ActionController::Api
      rescue_from ActiveRecord::RecordNotFound, with: :not_found

      private
    
      def not_found
         render json: { error: 'not found' }, status: :not_found       
      end   
    end
  end
end

但最有可能的是,你根本就不需要这个。Rails通过发送一个404 - Not Found响应来在框架级别拯救ActiveRecord::RecordNotFound。客户端不需要任何上下文,除了本例中的状态代码,返回完全不必要的JSON错误消息响应是一个反模式。

相关问题