Rails 컨트롤러에서 모든 예외 포착


89

다음과 같이 rails 컨트롤러에서 포착되지 않은 모든 예외를 포착하는 방법이 있습니까?

def delete
  schedule_id = params[:scheduleId]
  begin
    Schedules.delete(schedule_id)
  rescue ActiveRecord::RecordNotFound
    render :json => "record not found"
  rescue ActiveRecord::CatchAll
    #Only comes in here if nothing else catches the error
  end
  render :json => "ok"
end

감사합니다

답변:


93
begin
  # do something dodgy
rescue ActiveRecord::RecordNotFound
  # handle not found error
rescue ActiveRecord::ActiveRecordError
  # handle other ActiveRecord errors
rescue # StandardError
  # handle most other errors
rescue Exception
  # handle everything else
  raise
end

39
예외를 포착하지 않는 규칙이 아닙니까?
RonLugge 2014

2
그러나 rescue => e블록에서만 모든 유형을 잡을 수 있습니까?
Matrix

7
@RonLugge 그것은 전적으로 당면한 상황에 달려 있습니다. 경험상 "절대"를 적용하는 것은 나쁜 생각입니다.
Justin Skiles 2015

11
@JustinSkiles Catching Exception은 구문 오류 (및 인터럽트 신호도)를 포착합니다. 프로덕션 코드에서이 작업을 수행 할 수있는 좋은 시나리오를 하나주세요. 신호를 직접 잡아서 얻을 수 있지만, 신호 처리기를 만들고 있음을 분명히하기 위해 명시 적으로해야합니다. 예외를 잡는 것뿐입니다. 잡으려고하지 말아야 할 것들도 잡습니다.
RonLugge

6
예외에서 구조하는 것이
정상인

199

rescue_from 메소드를 정의 할 수도 있습니다.

class ApplicationController < ActionController::Base
  rescue_from ActionController::RoutingError, :with => :error_render_method

  def error_render_method
    respond_to do |type|
      type.xml { render :template => "errors/error_404", :status => 404 }
      type.all  { render :nothing => true, :status => 404 }
    end
    true
  end
end

목표가 무엇인지에 따라 컨트롤러별로 예외를 처리하지 않는 것을 고려할 수도 있습니다. 대신 exception_handler gem 과 같은 것을 사용하여 예외에 대한 응답을 일관되게 관리하십시오. 보너스로,이 접근 방식은 요청 구문 분석 또는 애플리케이션에서 볼 수없는 데이터베이스 연결 오류와 같이 미들웨어 계층에서 발생하는 예외도 처리합니다. exception_notifier의 보석도 관심이있을 수 있습니다.


4
DRY 방식으로 예외를 포착 할 수 있으므로 훨씬 더 편리합니다.
m33lky

그리고 매개 변수없이 rescue_from을 사용한다면? 구조와 동일하게 작동합니까? 모든 오류를 잡아?
minohimself

2
나쁜 습관 rescue_from Exception아닌가요? 나의 이해는에서 구출하는 것이 좋습니다 것입니다 StandardError같은 것들 때문에, SyntaxError그리고이 LoadError잡힌되지 않습니다.
lobati 2014-08-22

예, '예외'를 ​​구하는 것은 잘못된 형태입니다. 문제가 될 수있는 이유는 Avdi Grimm의 "Exceptional Ruby"를 참조하십시오.
Midwire

34

유형별로 예외를 포착 할 수 있습니다.

rescue_from ::ActiveRecord::RecordNotFound, with: :record_not_found
rescue_from ::NameError, with: :error_occurred
rescue_from ::ActionController::RoutingError, with: :error_occurred
# Don't resuce from Exception as it will resuce from everything as mentioned here "http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby" Thanks for @Thibaut Barrère for mention that
# rescue_from ::Exception, with: :error_occurred 

protected

def record_not_found(exception)
  render json: {error: exception.message}.to_json, status: 404
  return
end

def error_occurred(exception)
  render json: {error: exception.message}.to_json, status: 500
  return
end

2
Exception직접 구조하지 않도록주의하십시오 . 참조 stackoverflow.com/questions/10048173/...
의 Thibaut 바레

10

rescue 인수가 없으면 오류가 복구됩니다.

따라서 다음을 원할 것입니다.

def delete
  schedule_id = params[:scheduleId]
  begin
    Schedules.delete(schedule_id)
  rescue ActiveRecord::RecordNotFound
    render :json => "record not found"
  rescue
    #Only comes in here if nothing else catches the error
  end
  render :json => "ok"
end

8
부실한 질문이지만이 대답은 올바르지 않습니다. 인수 핸들이없는 구조에만 StandardError의 robots.thoughtbot.com/rescue-standarderror-not-exception
키스 가디스

0

실제로 모든 것을 포착하고 싶다면 자신 만의 예외 앱을 생성하기 만하면 일반적으로 PublicExceptions 미들웨어가 처리하는 동작을 사용자 지정할 수 있습니다. https://github.com/rails/rails/blob/4-2 -stable / actionpack / lib / action_dispatch / middleware / public_exceptions.rb

다른 답변은 당신을 위해 이것을하는 보석을 공유하지만 실제로는 그들을보고 스스로 할 수없는 이유가 없습니다.

주의 사항 : 예외 처리기에서 예외를 발생시키지 않도록하십시오. 그렇지 않으면 못생긴 FAILSAFE_RESPONSE https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L4-L22

BTW, 컨트롤러의 동작은 복구 가능에서 비롯됩니다 : https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/rescuable.rb#L32-L51

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.