2

I'm trying to send all rails errors as a notification, without disturbing other rescues.

ApplicationController:

class ApplicationController < ActionController::Base
around_filter :notify_errors

  def notify_errors
    begin
      yield
    rescue => e
      Notification.send_to(:admin, e)
    end
  end
end

SomeController function:

  def send_date
    date = Date.strptime('10/100/2013', '%m/%d/%Y')
    render json: {success: true, date: date}
  rescue ArgumentError
    render json: {success: false, msg: 'Bad date'}
  end

I get the "Bad date" json but not the Notification.send_to(:admin, e).

Shalev Shalit
  • 1,945
  • 4
  • 24
  • 34

2 Answers2

2

Raise again your exception.

def send_date
    date = Date.strptime('10/100/2013', '%m/%d/%Y')
    render json: {success: true, date: date}
rescue ArgumentError => e
    render json: {success: false, msg: 'Bad date'}
    raise e
end
coorasse
  • 5,278
  • 1
  • 34
  • 45
1

Is there a way to make it easier for each reraise error? A global solution or a function?

You could monkeypatch raise.

module RaiseNotify
  def raise(msg_or_exc, msg=msg_or_exc, trace=caller)
    Notification.send_to(:admin, msg_or_exc) if msg_or_exc.kind_of? StandardError
    fail msg_or_exc, msg=msg_or_exc, trace
  end
end

module Kernel
  include RaiseNotify
end

I haven't tested this, it would probably have impact beyond Rails, and I think it's a bad idea! Personally, I'd just call the notification code inside the initial rescue clause.

def send_date
  date = Date.strptime('10/100/2013', '%m/%d/%Y')
  render json: {success: true, date: date}
rescue ArgumentError => e
  Notification.send_to(:admin, e)
  render json: {success: false, msg: 'Bad date'}
end

This may be shortened with a method:

def rescue_with_notify error_type=ArgumentError
  *yield 
rescue error_type => e      
  Notification.send_to(:admin, e)
  [nil,false]
end   

The idea would be to wrap what you wish to check, and respond with an array, the end of which would be the "success" flag.

def send_date date_string
  date,success = rescue_with_notify do
    Date.strptime(date_string, '%m/%d/%Y') 
  end
  success = true if success.nil?
  date ||= "Bad date"
  render json: {success: success, date: date} 
end  

But this is adding complexity and maybe extra lines for very little in return. I'd stick with pasting the notification code into rescue clauses as and when it's required.

ian
  • 12,003
  • 9
  • 51
  • 107