How to setup a generic error/exception handler callback in Ruby? - ruby-on-rails

I’m working on this issue: Rails exception notifier in rake tasks
My question: Is there any function/plugin/gem/whatever to setup a generic error/exception handler callback as in PHP with set_error_handler and set_exception_handler?
I need a way to register a callback function used as a catchall outside any begin .. rescue .. end block. For example:
def my_handler *args
# exception processing code here
end
some_magic_method my_handler
raise "An Exception" # this will be handled by my_handler
In PHP this could be achieved with the set_exception_handler function. Is there any such function in Ruby/Rails?
If such feature exists I could solve my previous issue in a simple way.
A Rails-only solution would be fine for my needs.

I don't believe Ruby provides a way to do this, either with exceptions or with throw/catch. In general, doing something this way is a code smell and something to avoid. It makes control flow extremely hard to figure out. I would try to find some other way to approach the problem if at all possible.

If you want to do this in the HTTP Request-handling cycle you may use an around filter in your application controller:
class ApplicationController < ActionController::Base
around_filter do |controller, action|
action.call
rescue ExceptionXPTO
# ... handle the exception ...
end
end

I found a partial solution to my issue which works for the simple case I mentioned in the question. However this can not catch the exception, but it can be useful if someone needs only exception logging or reporting.
#!/usr/bin/env ruby
at_exit do
if $!
puts "Program ended with an exception #{$!.message}"
puts $!.backtrace.join("\n")
# or log the exception here
end
end
loop do
value = rand(3)
puts "Value is #{value}"
break if value == 2
raise "An Exception" if value == 0
end
puts "Program ended normally"

Related

How to check for errors in Ruby as IntelliJ does?

Recently I had a problem with a Rails application with the following code:
class MyBaseController < ApplicationController
def error(a, b)
# ...
end
end
class MyController < MyBaseController
def my_action
begin
another_method
rescue e
# The next line had a typo, it should
# have been "e" instead of "error" and
# hence it caused and unhandled exception
logger.error("the error was #{error}")
# ...
end
# ...
end
end
As you can see the logging statement will fail as it will try to call the error method from MyBaseController instead of getting the value of e.
This was an honest mistake but from what I see it could have been prevented: when I opened my application in IntelliJ with the Ruby plugin it marked the error with a red squiggle. Is not the first time I've seen one of these errors
My question is: Is there any Gem or tool (besides Intellij) to detect this kind of problems so I can add to my Rakefile and run it in my toolchain before my application gets deployed?
You could add debugger anywhere before or after any code you would like to trace.
Once you do the action from the browser, your running server in shell will pause the work and give you the ability to trace your code and test it.
I would recommend you to read more about debugging Rails applications.
Click here to read more about rails debugging

delayed_job - handling job return value

I am using delayed_job to perform a system call. This system call invokes a Groovy script.
class Job
def perform
command "groovy file.groovy"
system command
end
def success(job)
# handle success
end
def error(job, exception)
# handle error, exception
end
end
This is all working perfectly but I always get back a "success" status since my groovy always exits correctly. I am currently throwing RuntimeExeptions in the Groovy Script to provoke failing job. When I call system "groovy progra.groovy" and it raises an exception (The groovy program raises an Exception), the return value of system call is, as expected false. But when doing the same via delayed_job, it never accesses the def error method but the def success method.
Do you have any advise on how delayed_job actually controls the returns of the perform method? When does it enter the error or failure hook. Unfortunately I have not found anything on this topic in the documentation.
Thanks in advance
Have you tried something like this :
def perform
command = "groovy file.groovy"
system command || raise "Error executing command : #{command}"
end
I'm pretty sure delayed_job wraps the perform call in a rescue block and call success or error based on any exception it catches.

Testing module without Rails

I've got some Rspec tests that I'm using to test a module. The module is used by a number of models in my Rails app. In order to keep testing time down to a minimum, I want to avoid loading Rails when testing my module.
The problem is that there are a few methods that contain rescues and those rescues mention the Rails debugger. When Rspec sees the capital 'r' in Rails, it has a bad time because it considers it an uninitialized constant.
I was hoping that if I wrapped up the logging info into its own method, I could avoid the problem. Here's what I came up with. But if I go down this road, I would need to stub either the rescue code or or the log_info method. Is that right? How would I do that? And which one should I stub?
def download_robots_file(page)
file = Net::HTTP.get(URI("#{page}robots.txt"))
rescue StandardError => ex
log_info('robot_file', ex)
end
....
private
def log_info(problem, exception_issue)
Rails.logger.debug("Couldn't download #{problem}: " + exception_issue.inspect)
end
You can add to stub chain method that you want to stub.
Rails.stub_chain(:logger).and_return(mocked_logger_instance)
Un-stub in the end with:
Rails.unstub(:logger)
All credits go to mister on following link How to rspec mock ruby rails logger class

Testing an exception is thrown when using get with Ruby on Rails

I want to verify that an exception is being thrown in some function tests by calling get :methodname, :params. I had expected just making this call and then verifying the result is a 500 would be sufficient, but rails is failing the test as soon as the exception is reached in the get. While I figure I could go ahead and wrap the get in a rescue and verify the exception is thrown myself, and would hope there's a better method for doing this.
What's the best way to verify an exception is thrown when using a get in your tests?
You can do:
def test_sommat
assert_raises SomeException do
get :methodname, params
end
end

How to rescue exception in model?

In Rails.
Exception can rescue in controller class but in model class can not.
How to rescue exception in model?
You can do exception handling anywhere in a rails application, as it's part of Ruby, not part of Rails. Wherever you want to catch errors, just wrap it as so:
begin
SomethingElse.doSomething(x, y)
rescue Exception
ErrorLogger.log(Time.now, "Something went wrong!")
end
Please note that you should always "rescue Exception" instead of just "rescue". Just using "rescue" will only catch StandardError, which is a subclass of Exception (meaning something might get through that you don't want to get through).
Also as usual, you can raise an exception by doing:
raise ArgumentError, "Illegal arguments!"
anywhere in your code, be it a model or controller.
Unless I'm mistaken you can use error handling anywhere in Ruby. What are you trying to do?

Resources