So in my application_controller I have a helper method that raises an exception in a certain case, and a rescue_from for that exception in the same file. The structure looks something like the following:
application_controller.rb:
class ApplicationController < ActionController::Base
helper_method :my_method
def my_method
begin
# some code
rescue xyz
# some code
unless something
raise MyException.new()
end
rescue
raise MyException.new()
end
end
rescue_from 'MyException' do |e|
# some code
end
class MyException < StandardError; end
end
For some reason, when MyException is raised in my helper method, it is not caught by the rescue_from. I'm honestly not sure how to proceed...I don't think putting the rescue_from before the method would affect anything, since I have more than one handler defined like this and they work fine.
Related
I want to use rescue_from method on a model concern but neither exception error is rescued to the method i specified:
require "active_support/concern"
module CustomErrorHandler
extend ActiveSupport::Concern
include ActiveSupport::Rescuable
included do
rescue_from StandardError, with: :capture_error
end
private
def capture_error(e)
puts "Error catched!"
end
end
class FooClass
include CustomErrorHandler
def some_action
raise StandardError, 'Error'
end
end
err = FooClass.new
err.some_action
Traceback (most recent call last):
2: from (irb):28
1: from (irb):23:in `some_action'
StandardError (Error) # Didn't catch the error!
Anyone can help me on how can i solve this? Thanks!
This idea is fundamentially broken.
rescue_from is basically just syntactic sugar for:
class ThingsController < ApplicationController
around_action :wrap_in_a_rescue
def show
raise SomeKindOfException
end
private
def wrap_in_a_rescue
begin
yield
rescue SomeKindOfException
do_something_else
end
end
def do_something_else
render plain: 'Oh Noes!'
end
end
It only works because the controller declares a callback.
Its use makes sense in a controller as it rescues exceptions that occur in its callbacks as well as in the method itself and can be used with inheritiance to customize the error responses. It use does not make very much sense outside of that context.
While you could maybe fix this code by including ActiveSupport::Callbacks and declaring the requisite callbacks it is most likely a very overcomplicated solution to the original problem which can most likely be handled with a simple rescue or composition.
I am trying to create my own StandardError exception, but I cannot seem to fire rescue_from with the raise. The error is raised but never rescued. I built a simple application to try it, as follows:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
class ApplicationController::LocationInvalid < StandardError
end
rescue_from ApplicationController::LocationInvalid, with: :reset_it
raise ApplicationController::LocationInvalid
private
def reset_it(exception)
session.clear
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
puts 'Reset it processed'
end
end
When I wrap the raise in begin/rescue/end, it prints e as ApplicationController::LocationInvalid:
begin
raise ApplicationController::LocationInvalid
rescue => e
puts e
end
Output:
Started GET "/" for 127.0.0.1 at 2015-08-21 15:19:32 -0400
ApplicationController::LocationInvalid
I've tried various forms of specifying the ApplicationController class and not with no change in the results...
According to source code of Rails https://github.com/rails/rails/blob/f62fb985b6a7b90872148f0786219c9cc94c9356/actionpack/lib/action_controller/metal/rescue.rb#L32
rescue_with works only during process_action call but you are raising exception during class evaluation. Probably the easiest way how to test it is to create simple controller with some action and try to raise exception during that action and rescue_with should work.
Rails's :rescue_from takes in a specific exception type and a method as parameter as follow:
class ApplicationController < ActionController::Base
rescue_from User::NotAuthorized, with: :deny_access # self defined exception
rescue_from ActiveRecord::RecordInvalid, with: :show_errors
rescue_from 'MyAppError::Base' do |exception|
render xml: exception, status: 500
end
protected
def deny_access
...
end
def show_errors(exception)
exception.record.new_record? ? ...
end
end
but this implies that it will deal with the specified exception in the same way ALL ACROSS the controller.
What if I want to handle an exception type differently based on what method the exception is raised from, Example:
class MyController < ActionController::Base
def method_1
# Do Something
rescue MyCustomError => e
handle_exception_for_method_1(e)
end
def method_2
# Do Something
rescue MyCustomError => e
handle_exception_for_method2(e)
end
protected
def handle_exception_for_method_1(exception)
# Do Something
end
def handle_exception_for_method_2(exception)
# Do Something
end
end
I have the following questions:
Can this be done by using :rescue_from as well (with any sort of options to pass in)?
If not, is there any better solution of dealing with this kind of situations?
(Kind of off topic but) Is it a bad practice to handle the same type of error differently in different methods in general?
Rails provides access to the controller and action names through controller_name and action_name methods. You could use this to handle exceptions differently based on the what method the exception was raised.
Example:
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordInvalid, with: :show_errors
protected
def show_errors
if action_name == "create"
...
elsif action_name == ...
...
end
end
I have this code in application controller:
# Method to capture and handle all exceptions
rescue_from Exception do |ex|
Rails.logger.debug ex
do_stuff(ex)
end
I want to move this into a module and then:
class ApplicationController < ActionController::Base
include 'module'
...
Right now my module looks like:
# lib/exception_mailer.rb
require 'action_mailer'
require 'active_support'
module ExceptionMailer
# Method to capture and handle all exceptions
rescue_from Exception do |ex|
...
And I am getting: undefined method 'rescue_from' for ExceptionMailer:Module
I've googled 'how do i include rescue_from in a module?' -- and I'm still a little lost.
module Exceptionailer
# http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
extend ActiveSupport::Concern
included do
rescue_from Exception do |ex|
...
end
end
end
I tried almost everything on web, all I want is to call a method whenever an exception like "ActiveRecord::RecordNotFound" or "No route matches" appears.
Rescues from ApplicationController does not work, but why?
class ApplicationController < ActionController::Base
protect_from_forgery
private
def self.send_report_error(message)
Notifier.page_failure(message).deliver
end
rescue ActiveRecord::RecordNotFound
# handle not found error
send_report_error ActiveRecord::RecordNotFound.to_s
rescue ActiveRecord::ActiveRecordError
# handle other ActiveRecord errors
send_report_error ActiveRecord::ActiveRecordError.to_s
rescue # StandardError
# handle most other errors
send_report_error "common error"
rescue Exception
# handle everything else
send_report_error "common exception"
end
Use rescue_from. For example:
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :send_report_error
end
http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html