Reputation: 3430
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
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
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,
Add the gem in Gemfile
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]}
}
Upvotes: 1