2010-09-12 13 views
73

Czy istnieje sposób, aby złapać wszystkie uncatched wyjątków w kontroler szyny, jak to:złapać wszystkie wyjątki w kontroler szyny

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

Dziękuję

Odpowiedz

75
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 
+25

Czy nie jest regułą, aby NIGDY nie złapać wyjątku? – RonLugge

+1

, ale jak mogę przechwycić wszystkie typy tylko w bloku 'rescue => e'? – Matrix

+4

@RonLugge zależy całkowicie od sytuacji. stosowanie "nigdy" z reguły jest złym pomysłem. –

9

rescue bez argumentów uratuje żadnego błędu.

Więc, będziesz chciał:

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 
+6

Stale pytanie, ale odpowiedź jest błędna. ratowanie bez obsługi tylko argumentów StandardError http://robots.thoughtbot.com/rescue-standarderror-not-exception – karmajunkie

178

Można również zdefiniować metodę 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 

W zależności od tego, jaki jest Twój cel, możesz również rozważyć NIE obsługę wyjątków na podstawie poszczególnych kontrolerów. Zamiast tego użyj czegoś podobnego do klejnotu exception_handler, aby konsekwentnie zarządzać reakcjami na wyjątki. Jako bonus, podejście to będzie również obsługiwać wyjątki, które występują w warstwie oprogramowania pośredniego, takie jak analizowanie żądań lub błędy połączenia z bazą danych, których aplikacja nie widzi. Klejnot exception_notifier może również zainteresować.

+3

Jest to jeszcze bardziej przydatne ponieważ pozwala wychwytywać wyjątki w sposób DRY. – m33lky

+0

A jeśli użyję rescue_from bez parametrów? czy zachowacie się tak samo jak ratowanie? złapać wszystkie błędy? – minohimself

+2

Czy to nie jest zła praktyka "rescue_from Exception"? Rozumiem, że lepiej jest uratować z 'StandardError', więc rzeczy takie jak' SyntaxError' i 'LoadError' nie zostaną przechwycone. – lobati

19

Można złapać wyjątki według typu:

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

Uważaj, aby nie uratować bezpośrednio przed 'Wyjątkiem'; zobacz http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby –

0

Właściwie, jeśli naprawdę chcesz, aby złapać wszystko, po prostu stworzyć własną aplikację wyjątkami, który pozwala ci dostosować zachowanie, które jest zazwyczaj obsługiwany przez PublicExceptions middleware: https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/public_exceptions.rb

A kilka innych perełek odpowiedzi na akcje, które wykonują to dla ciebie, ale naprawdę nie ma powodu, żebyś mógł po prostu na nie patrzeć i zrobić to sam.

Ograniczenie: upewnij się, że nigdy nie zgłaszasz wyjątku do obsługi wyjątku. W przeciwnym razie pojawi się brzydki FAILSAFE_RESPONSE https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L4-L22

BTW, zachowanie w kontrolerze pochodzi z rescuable: https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/rescuable.rb#L32-L51

Powiązane problemy