coding addicted
coding addicted

Reputation: 3430

Custom error redirect, flash notice not working

In a classic Rails app I tried to handle errors with a custom controller redirecting to the root_path with a flash message.

routes:

match "/404", :to => "errors#not_found", :via => :all
match "/500", :to => "errors#internal_server_error", :via => :all

Error controller:

class ErrorsController < Admin::AdminController
  def not_found
    redirect_to admin_path, notice: "Sorry, reccord not found"
  end

  def internal_server_error
    redirect_to root_path, notice: "Sorry, something went wrong"
  end
end

The error redirect_to admin_path or root_path (I've tried other paths to be sure it's not related)

The admin path just show a dashboard:

class Admin::StaticController < Admin::AdminController
  def dashboard
    flash.keep
    byebug
  end
end

I tried to add the flash.keep even if there's no multiple redirection. Byebug stops the process to help to see what's happening but flash notice appears nil at this point.

Logs (cleaned a little):

Started GET something_not_possible_to_get
Completed 404 Not Found in 13ms (ActiveRecord: 2.3ms)
ActiveRecord::RecordNotFound
Processing by ErrorsController#not_found as HTML
Redirected to the_path
Started GET "/" (root_path)
ByeBug stopping here and notice is nil
continue just render the page as expected but without the notice

What I'm trying to achieve is to redirect users getting error (404 or 500) to the root_path or another path, let them know something went wrong with a notification message (flash) but without blocking them on the classic Rails error page. Then I could be able to implement internal errors handling (let say email to the admin/owner of the app for instance).

I tried the keep.flash without success.

Why the notice message is dropped? And why this is happening only with errors (I have a lot of redirect_to with notice that are working fine)?

Upvotes: 4

Views: 2149

Answers (2)

B Seven
B Seven

Reputation: 45943

In order to use these routes,

match "/404", :to => "errors#not_found", :via => :all
match "/500", :to => "errors#internal_server_error", :via => :all

You have to set the exception handler in application.rb:

module RailsApp
  class Application < Rails::Application
    config.exceptions_app = self.routes

Upvotes: 0

Sahil
Sahil

Reputation: 3358

You do not have to create ErrorsController, instead you can catch the error and perform any action you want to.

Also you can use exception_notification gem to send error related mails to the configured account.

In application controller

class ApplicationController < ActionController::Base 
   rescue_from ActiveRecord::RecordNotFound, :with => :not_found
   rescue_from ActiveRecord::RecordInvalid, :with => :internal_server_error
   #some other errors that can be captured
   #rescue_from ActionController::MissingFile, :with => :render_404
   #rescue_from ActionController::RoutingError, :with => :render_404
   #rescue_from ActionView::TemplateError, :with => :render_500
   #rescue_from Errno::ENOENT, :with => :render_404
   #rescue_from Errno::EACCES, :with => :render_404

  def not_found
    notify(error)
    redirect_to admin_path, notice: "Sorry, reccord not found"
  end

  def internal_server_error
    notify(error)
    redirect_to root_path, notice: "Sorry, something went wrong"
  end

  def notify(exception)
   ExceptionNotifier::Notifier.exception_notification(request.env, exception,
    data: {message: 'An error occured'}).deliver
  end

end

Setting up exception_notification gem,

  1. Add the gem in Gemfile

  2. Setup mail:

production.rb (implement the same in development.rb to test it out):

MyApp::Application.configure do
  #Action Mailer configuration to send emails
  config.action_mailer.delivery_method = :smtp

  config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :domain => "google.com",
    :user_name => "[email protected]",
    :password => "123",
    :authentication => "plain",
    :enable_starttls_auto => true 
  }
end

   MyApp::Application.config.middleware.use ExceptionNotification::Rack,
  :email => {
    :email_prefix => "[error in]",
    :sender_address => %{[email protected]},
    :exception_recipients => %w{[email protected]}
  }
  1. Check the code above in Application Controller at the beginning of the answer.

Upvotes: 1

Related Questions