Nắm bắt tất cả các trường hợp ngoại lệ trong bộ điều khiển đường ray


89

Có cách nào để nắm bắt tất cả các ngoại lệ chưa từng có trong bộ điều khiển đường ray, như sau:

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

Cảm ơn bạn

Câu trả lời:


92
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

38
Không phải là quy tắc để KHÔNG BAO GIỜ bắt Ngoại lệ?
RonLugge

2
nhưng làm thế nào tôi có thể bắt tất cả các loại chỉ trong rescue => ekhối?
Ma trận

7
@RonLugge nó phụ thuộc hoàn toàn vào tình hình hiện tại. áp dụng "không bao giờ" như một quy tắc ngón tay cái là một ý tưởng tồi.
Justin Skiles

11
@JustinSkiles Catching Exception sẽ bắt lỗi cú pháp (và cả tín hiệu ngắt). Hãy cho tôi một kịch bản tốt để thực hiện điều đó trong mã sản xuất. Bắt tín hiệu trực tiếp mà tôi có thể nhận được, nhưng bạn cần làm như vậy một cách rõ ràng để làm rõ rằng bạn đang tạo một trình xử lý tín hiệu. Chỉ bắt Exception ... xấu, ý kiến ​​tồi. Nắm bắt ngay cả những thứ bạn không nên cố bắt.
RonLugge

6
Một trong số ít các trường hợp phổ biến nơi nó lành mạnh để giải cứu từ Exception là dành cho mục đích khai thác gỗ / báo cáo, trong trường hợp này bạn nên ngay lập tức lại tăng ngoại trừ: stackoverflow.com/a/10048406/252346
aelesbao

198

Bạn cũng có thể xác định một phương thức 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

Tùy thuộc vào mục tiêu của bạn là gì, bạn cũng có thể muốn xem xét KHÔNG xử lý các trường hợp ngoại lệ trên cơ sở từng bộ điều khiển. Thay vào đó, hãy sử dụng một cái gì đó giống như gem exception_handler để quản lý phản hồi cho các ngoại lệ một cách nhất quán. Như một phần thưởng, cách tiếp cận này cũng sẽ xử lý các trường hợp ngoại lệ xảy ra ở lớp phần mềm trung gian, như phân tích cú pháp yêu cầu hoặc lỗi kết nối cơ sở dữ liệu mà ứng dụng của bạn không nhìn thấy. Các exception_notifier đá quý cũng có thể quan tâm.


4
Điều này thậm chí còn tiện dụng hơn vì nó cho phép bắt các trường hợp ngoại lệ theo cách KHÔ.
m33lky

Và nếu tôi sử dụng Rescue_from mà không có thông số? điều đó sẽ hoạt động giống như giải cứu? bắt hết lỗi?
minohimself

2
Nó không phải là nó thực hành xấu rescue_from Exception? Tôi hiểu rằng tốt hơn là nên giải cứu khỏi StandardError, để những thứ như SyntaxErrorLoadErrorkhông bị bắt.
lobati

Vâng, đó là hình thức xấu để giải cứu 'Exception'. Hãy xem "Viên hồng ngọc ngoại hạng" của Avdi Grimm để biết lý do tại sao điều đó có thể có vấn đề.
Midwire

34

Bạn có thể bắt các ngoại lệ theo loại:

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
Cẩn thận không giải cứu từ Exceptiontrực tiếp; xem stackoverflow.com/questions/10048173/…
Thibaut Barrère

10

rescue không có đối số sẽ giải cứu bất kỳ lỗi nào.

Vì vậy, bạn sẽ muốn:

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
Câu hỏi cũ, nhưng câu trả lời này không chính xác. cứu hộ không có cán Lý lẽ duy nhất StandardError robots.thoughtbot.com/rescue-standarderror-not-exception
Keith Gaddis

0

Trên thực tế, nếu bạn thực sự muốn nắm bắt mọi thứ , bạn chỉ cần tạo ứng dụng ngoại lệ của riêng mình, cho phép bạn tùy chỉnh hành vi thường được xử lý bởi phần mềm trung gian PublicExceptions: https://github.com/rails/rails/blob/4-2 -stable / actionpack / lib / action_dispatch / middleware / public_exceptions.rb

Một loạt các câu trả lời khác chia sẻ những viên ngọc làm điều này cho bạn, nhưng thực sự không có lý do gì bạn không thể chỉ nhìn vào chúng và tự mình làm điều đó.

Lưu ý: hãy đảm bảo rằng bạn không bao giờ nêu ra một ngoại lệ trong trình xử lý ngoại lệ của mình. Nếu không, bạn sẽ nhận được một FAILSAFE_RESPONSE xấu xí https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L4-L22

BTW, hành vi trong bộ điều khiển đến từ có thể cứu được: https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/rescuable.rb#L32-L51

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.