Non-fatal rescue in Rails - ruby-on-rails

I'm trying to run a command that might fail sometimes. When it fails, it throws an exception.
What I'd like it to do is just log the error quietly and continue executing the next line below it, rather than aborting and going into the 'rescue' block. How should I approach this?
My current code is as follows:
rescue_from 'Gibbon::MailChimpError' do |exception|
logger.error("MAILCHIMP: #{exception}")
end
When I call the Mailchimp API, sometimes there is an error, and this disrupts the flow of my application. I just want it to carry on executing as if nothing has happened, and just note there was an error in the log.

How about something like this:
def rescuing(&block)
begin
yield
rescue NameError => e
puts "(Just rescued: #{e.inspect})"
end
end
rescuing do
puts "This is dangerous"
raise NameError
end
puts "... but I'm still alive"
Obviously, you'd have to replace NameError with the exception you want to be protected against.

Related

Execute method on exception raised without rescuing

I'm using Sidekiq, and I'd like to execute a method when an exception is raised in a background job, without rescuing the error.
Currently, I have:
begin
# job
rescue => SomeError
# run method
end
However, since it rescues the error, it does not go in the "failed" section of Sidekiq.
I'd like to execute code when an exception is raised, but without rescuing it. How can I do this ?
Just re-raise and you are all set.
begin
# job
rescue => SomeError
# run method
raise
end

Rails not catching exception in rescue block

User model has defined indexes to be searched using ThinkingSphinx. However when I stop my searchd deamon, I would like my method to fail gracefully and not throw an error. Normally I do this by using a rescue block for catching exceptions. But in this case, it still throws the error and the puts statement is never executed.
def search_users(key)
begin
search_results = User.search(key,options)
rescue Exception
puts "Hello World!!!"
search_results = []
end
return search_results
end
Following is the error i get:
Riddle::ConnectionError (Connection to 127.0.0.1 on 3201 failed. Connection refused - connect(2)):
Is there any way out?
Solved it.
Add the :populate => true option to your search calls.
Normally, Thinking Sphinx lazily loads search results (allowing for
sphinx scopes and such) - but if you want the rescue to take effect,
then you'll need to force the results to load immediately - hence the
:populate option.
Refer the link posted above for further reading.
Given ruby return semantics, you can compress your code:
def search_users(key)
begin
User.search(key,options)
rescue
puts "Hello World!!!"
[]
end
end
It is evil to rescue Exception. Just use rescue, which rescues StandardError, which captures most of the stuff you want it to. Otherwise you also capture SyntaxError, LoadError, SystemExit and other stuff you don't intend. In this case, rescue Riddle::ConnectionError is appropriate, but not necessary.

How to rescue the error exception raised by the `constantize` method?

I am using Ruby on Rails 3.2.2 and I would like to properly rescue the following process flow by raising a "custom" error message:
def rescue_method
# sample_string.class
# => String
# sample_string.inspect
# => "ARubyConstantThatDoesNotExist"
begin
build_constant(sample_string)
rescue
raise("My custom error message: #{build_constant(sample_string)} doesn't exist.")
end
end
def build_constant(sample_string)
"AModule::#{sample_string}".constantize
end
Note: I feel "forced" to use the constantize method also in the raised "custom" message in order to DRY code...
When the rescue_method is executed it seems that the raise("My custom error message") code is never executed and I get the following error:
uninitialized constant AModule::ARubyConstantThatDoesNotExist
How to properly display the raised "custom" message (since a further error exception is raised in the subsequent raised "custom" message)? What do you advice about?
The problem is that your build_constant method is doing two things:
Building the class name.
Turning the name into a class using constantize.
One of those things wants to use the other when an exception is raised. A simple solution is to pull those separate tasks apart:
def build_class_name(sample_string)
"AModule::#{sample_string}"
end
def rescue_method
name = build_class_name(...)
name.constantize
rescue NameError
raise("My custom error message: #{name} doesn't exist.")
end
You should also be more specific about the exception you're looking for so I added that for free.
If you don't want to rely on catching any exception, you could use safe_constantize (https://apidock.com/rails/ActiveSupport/Inflector/safe_constantize).
Same purpose as constantize but will return nil instead, whenever a Module does not exist.
'UnknownModule::Foo::Bar'.safe_constantize # => nil
begin
"AModule::#{sample_string}".constantize
rescue SyntaxError, NameError => err
raise("My custom error message")
end

Rails: Returning errors from Module to Rake task?

How do I pass an error from my Module back to the rake task that called it?
My rake task looks like this:
require 'mymodule.rb'
task :queue => :environment do
OPERATOR = Mymodule::Operator.new
begin
OPERATOR.initiate_call (1234567189)
rescue StandardError => bang
puts "Shit happened: #{ bang} "
end
end
And here is my module..
module Mymodule
class Operator
def initiate_call (number)
begin
# make the call
rescue StandardError => bang
flash[:error] = "Error #{bang}"
return
end
end
end
end
I also call this module from a controller so it would be nice to have an error handling solution that is more or less agnostic.
Running Rails 3. Any unrelated comments (i.e. suggestions) on my code structure are more than welcomed :)
Your Operator#initiate_call method traps StandardError exceptions so your rake task will never see them. I'd drop the rescue from initiate_call and let the caller deal with all the exception handling. Then, you'd have flash[:error] = "Error #{bang}" in your controller's exception handler and the rake task would remain as-is.
The basic approach is to push the error handling up the call stack all the way to someone that can do something about it; initiate_call can't really do anything useful with the exception so it shouldn't try to handle it.

How do I raise an exception in Rails so it behaves like other Rails exceptions?

I would like to raise an exception so that it does the same thing a normal Rails exception does. Specially, show the exception and stack trace in development mode and show "We're sorry, but something went wrong" page in production mode.
I tried the following:
raise "safety_care group missing!" if group.nil?
But it simply writes "ERROR signing up, group missing!" to the development.log file
You don't have to do anything special, it should just be working.
When I have a fresh rails app with this controller:
class FooController < ApplicationController
def index
raise "error"
end
end
and go to http://127.0.0.1:3000/foo/
I am seeing the exception with a stack trace.
You might not see the whole stacktrace in the console log because Rails (since 2.3) filters lines from the stack trace that come from the framework itself.
See config/initializers/backtrace_silencers.rb in your Rails project
You can do it like this:
class UsersController < ApplicationController
## Exception Handling
class NotActivated < StandardError
end
rescue_from NotActivated, :with => :not_activated
def not_activated(exception)
flash[:notice] = "This user is not activated."
Event.new_event "Exception: #{exception.message}", current_user, request.remote_ip
redirect_to "/"
end
def show
// Do something that fails..
raise NotActivated unless #user.is_activated?
end
end
What you're doing here is creating a class "NotActivated" that will serve as Exception. Using raise, you can throw "NotActivated" as an Exception. rescue_from is the way of catching an Exception with a specified method (not_activated in this case). Quite a long example, but it should show you how it works.
Best wishes,
Fabian
If you need an easier way to do it, and don't want much fuss, a simple execution could be:
raise Exception.new('something bad happened!')
This will raise an exception, say e with e.message = something bad happened!
and then you can rescue it as you are rescuing all other exceptions in general.

Resources