Search code examples
ruby-on-rails-3activerecordexception-notification

How to access exception recipients after initialisation with exception notification gem?


I want to be able to define the exception_recipients dynamically, based on the Rails environment. For example:

recipients = Rails.env == 'production'
   [email protected]
else
   User.current.email
end

However, from the docs:

Whatever::Application.config.middleware.use ExceptionNotification::Rack,
  :email => {
    :email_prefix => "[Whatever] ",
    :sender_address => %{"notifier" <[email protected]>},
    :exception_recipients => %w{[email protected]}
  }

In config/environments/production.rb where i don't have an ActiveRecord::Base connection yet.

How can I set the exceptions recipients after Rails has loaded?

Thanks


Solution

  • Custom Notifier

    You can create a custom notifier, which inherits from the EmailNotifier, which will use User.current.email in the non-production environments.

    # app/models/exception_notifier/custom_notifier.rb
    #
    module ExceptionNotifier
      class CustomNotifier < EmailNotifier
    
        def initialize(options)
          @fallback_exception_recipients = options[:fallback_exception_recipients]
          options[:exception_recipients] ||= options[:fallback_exception_recipients]
          super(options)
        end
    
        def call(exception, options = {})
          options[:exception_recipients] = [User.current.email] unless Rails.env.production?
          super(exception, options)
        end
    
      end
    end
    

    Initializer

    The fallback address can, for example, be passed from the initializer.

    # config/initializers/exception_notification.rb
    #
    Rails.application.config.middleware.use ExceptionNotification::Rack, {
      :custom => {
        :fallback_exception_recipients => %w{[email protected]},
        # ...
      }
    }
    

    current_user instead of User.current

    I'm not sure whether your User.current call will work here. But, you pass the current_user to the exception data as shown in the README.

    # app/controllers/application_controller.rb
    #
    class ApplicationController < ActionController::Base
      before_filter :prepare_exception_notifier
      private
      def prepare_exception_notifier
        request.env["exception_notifier.exception_data"] = {
          :current_user => current_user
        }
      end
    end
    

    Then, replace the above ExceptionNotifier::CustomNotifier#call method with this one:

    # app/models/exception_notifier/custom_notifier.rb
    #
    module ExceptionNotifier
      class CustomNotifier < EmailNotifier
    
        # ...
    
        def call(exception, options = {})
          unless Rails.env.production?
            if current_user = options[:env]['exception_notifier.exception_data'][:current_user]
              options[:exception_recipients] = [current_user.email]
            end
          end
          super(exception, options)
        end
    
      end
    end