简体   繁体   中英

rescue_from StandardError overridding other rescue_from blocks

I am trying to create a module that handles API errors that I include in my application_controller.rb . Here is my module's self.included function.

def self.included(clazz)
  clazz.class_eval do

    rescue_from ActiveRecord::RecordNotFound do |e|
      respond(:record_not_found, 404, e.message)
    end
    rescue_from ActiveRecord::RecordInvalid do |e|
      respond(:record_invalid, 422, e.record.errors.full_messages)
    end
    rescue_from ActionController::ParameterMissing do |e|
      respond(:bad_request, 400, e.message)
    end
    rescue_from StandardError do |e|
      respond(:standard_error, 500, e.message)
    end
  end
end

The problem I am having is that StandardError catches all errors including the other errors I have defined in the other rescue_from blocks.

I want to achieve something like this instead:

begin

rescue ActiveRecord::RecordNotFound => e

rescue ActiveRecord::RecordInvalid => e

rescue ActionController::ParameterMissing => e

rescue StandardError => e

end

Thanks for the help in advance.

I would refactor this into a single rescue_from and then drill down by checking e.class :

rescue_from StandardError do |e|
  case e.class
  when ActiveRecord::RecordNotFound
    respond(:record_not_found, 404, e.message)
  when ActiveRecord::RecordInvalid
    respond(:record_invalid, 422, e.record.errors.full_messages)
  when ActionController::ParameterMissing
    respond(:record_not_found, 400, e.message)
  else
    respond(:standard_error, 500, e.message)
  end
end

The problem is that rescue_from handlers are

Handlers are inherited. They are searched from right to left, from bottom to top, and up the hierarchy.

This means that the blocks are executed in reverse order so your 4 rescue_from s look more like:

begin
rescue StandardError => e
rescue ActionController::ParameterMissing => e
rescue ActiveRecord::RecordInvalid => e
rescue ActiveRecord::RecordNotFound => e
end

instead. The fact that the last handler added is the first one executed allows things such as a child controller to override a handler in a parent controller. So, to fix, simply reverse the order you define your rescue_from blocks and things should work as you intended.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM