There is a code in which every line can cause an exception and I want to continue my execution even if an error occurred in any of the lines of code
I will implement this in the below-mentioned way
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
is there any better way to handle this type of error handling if yes please explain how can I write better code
every line can cause an exception
please explain how can I write better code
You can write better code by not designing it in such a way that every line can raise an exception. Especially this idea that the code should "plough on ahead, regardless of any trail of errors are left in its wake".
At an extreme, you code could contain all sorts of spelling mistakes / invalid method calls / whatever, and your proposed design would attempt to continue executing the remainder of the code, regardless of how broken it is.
However, I cannot really give concrete advice on how to do this, without seeing some actual code.
Related
If I wanted to both rescue a potential error and catch a potential throw, how should I nest them? Are the two below equivalent, and it is just a matter of preference?
begin
catch(:some_throw) do
...
end
rescue SomeError
...
end
catch(:some_throw) do
begin
...
rescue SomeError
...
end
end
Its an opinion-based question, and one can argue either way. So, in my opinion...
If you are planning to return a value via throw, then, second option seems useful as it will let you rescue an error and throw some kind of default value.
Even if you were using throw and catch just to manage loop iterations and breaking out of it on certain conditions, second option still seems more readable and encapsulates all the logic inside the catch block.
They are not entirely equivalent. With the first alternative, the catch will only intercept values being thrown in the begin clause, while the second includes ones from rescue too.
That being said, if you are in the case, when the two are equivalent (aka you don't throw :some_throw in the rescue clause):
The argument for the first alternative would be that we tend to think that begin - rescue blocks enclose "regular" statements. throw - catch being rarely used and having a non-error semantic are more "regular"-y.
The argument for the second alternative would be that one should strive to enclose the least amount (only the possibly failing) of code in begin - rescue clauses.
Personally, I like the first one better.
i manage to do "something"(like deleting files,etc) when exit or exit! is called from Object.
by changing the method exit and exit! inside Object class. (at_exit is too unreliable)
but then the "something" never execute if there's error such as NameError, etc.
is there way so i can make "something" that still execute if there's error.
(any error possible if necessary).
something like at_exit but works with all errors
thanks in advance for assistance. and forgive me if there's already question ask for this.
i do search a lot before asking here. and found nothing.
edit: i don't know where the original author of the code place the method. since the original author load it from dll files in the exe program the author used for launcher. (i can only edit After the original code take place...). so i think i need another approach for this... but i manage to make a workaround for my problem... by putting begin rescue in other places that send data to the original object. i filter the data send and throw my own error before it reach the main program... so i guess this works too.
Borrowing from an answer on a different thread, and definitely along the lines of what Marek commented, this is how you should handle errors in Ruby:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
end
Original credit: Begin, Rescue and Ensure in Ruby?
I'm checking to see if there is any error message in a log file. If an error message found in a log file, then I use 'raise' statement to report the founding. However ruby stops running after executed the 'raise' statement, even when I use 'rescue'. I'd like script continue checking next log file for error after the 'raise' statement, but not sure how. Any help would be appreciated!
logs_all = s.sudo "egrep -i '#{error_message}' #{log_file}"
logs_all.each do |hostname, logs|
unless logs.empty?
puts line, "Unhappy logs on #{hostname}", line, logs
happy = false
end
begin
raise "Unhappy logs found! in #{log_file}" unless happy
rescue raise => error
puts error.message
end
end
Your rescue statement doesn't look right:
rescue raise => error
should be:
rescue => error
which is equivalent to:
rescue StandardError => error
If you rescue an exception and don't re-raise it, ruby will continue on. You can easily verify this with something like:
3.times do |i|
begin
raise "Raised from iteration #{i}"
rescue => e
puts e
end
end
You'll see that three lines of output are printed.
As a general practice though, you should avoid rescuing Exceptions unless you're going to do something at runtime to rectify the problem. Rescuing and not re-throwing exceptions can hide problems in your code.
And more generally, please follow Sergio's advice above and don't use exceptions as control flow.
Further Reading
I recommend looking over the Exceptions section of this ruby style guide - it will give you some quick pointers in the right directions.
Also, this answer about never rescuing Exception
You are using exceptions as control flow mechanism. Don't.
What is it that you want to do with unhappy logs? Print them? To a file, maybe? Do that, don't raise exceptions.
I have a ruby script that loops through a list of shortened urls (around 2,000 - 3,000 at a time). At the moment everything is peachy until a hit a url that is malformed, timedout etc. When an error occurs my script dies. How can I setup my loop to skip to the next record when/if such an error occurs.
my loop looks like this:
blah.foo do |barurl|
mymethod(barurl)
my mymethod looks like this:
def mymethod(barurl)
begin
stuff
...
return expandedurl
rescue
return "Problem expanding link"
end
end
Should my begin/end logic be wrapped around my loop instead of the method?
Because you need to skip the malformed url, you should use the exception message to control the loop
blah.foo do |barurl|
begin
mymethod(barurl)
rescue YourTypeOfException
next
end
end
and inside the method raise the exception
def mymethod(barurl)
stuff
...
raise YourTypeOfException, "this url is not valid"
...
end
I found the existing answers unsatisfying, and reading the documentation suggests to me that the OP had something more like the example suggested there in mind:
[0, 1, 2].map do |i|
10 / i
rescue ZeroDivisionError
nil
end
#=> [nil, 10, 5]
The docs specifically note that a rescue block permits the loop to continue on a caught exception (as indicated by the example).
Yes. All your method does is consume the exception and return another arbitrary object in order to indicate an error.
Your method shouldn't handle its own exceptional conditions. It is just rude on its part to make assumptions about how the caller will react.
blah.foo do |url|
begin
my_method url
rescue
next
end
end
Whether to skip to the next URL or print a message is not a decision the method should be making. Its only concern should be working with the URL.
With that said, you should simply let it propagate and only rescue from it when you can actually deal with it. Don't rescue from a TimeoutError if all you can do is return :timeout.
Do rescue when you need to clean up resources or simply let the user know an error occurred.
Also, rescuing from every possible error just to make them go away is a nice way to introduce bugs. Be as specific as possible.
having exception handling within your method is proper way of doing it, so your implementation is fine
i can only point some ruby sytax sugar to you:
def some_method
# here goes the code
rescue Exception => e
# here goes specific exception/error handling
rescue
# here goes error handling (not Exception handling though!)
else
# do this block when no exceptions are raised
ensure
# do this every time
end
btw you don't need return statements, last value of code block is always returned implicitly
ah i guess i misread your question in the "how to skip next record"
if you want to skip the record after current one that was incorrect you would have to return error code from your parsing method and set up skipping within your loop using break or next keywords
It should be inside the loop, so the loop structure isn't exited on an exception. But it looks like it already is--if you're rescuing inside the method that causes the exception, the loop should already continue normally, because it shouldn't be seeing the exception.
whenever there is an exception call that is raised, the script terminates.
do i have to resort to putting each action ? it gets very complicated fast.....
begin
#someaction
begin
#someaction2
rescue
end
rescue
end
You could use some sort of AOP mechanism to surround every method call with exception handling code (like Aquarium: http://aquarium.rubyforge.org/), or put rescue nil after every line of code, but I'm guessing that if you need to do that, then the exceptions raised are not really signalling exceptional situations in your app (which is bad) or you want to try to continue even in a situation where there's really no point to do so (which is even worse). Anyway I'd advise you to reconsider what you really need to do, because it seems to me that you are approaching the problem in a wrong way.
It's difficult to give a specific answer because I don't know what your program does.
But in general terms, I find that the best way to deal with this is to put the code that could fail into one or more seperate methods (and perhaps the method name should reflect this).
This has a number of advantages. First of all, it means that the rest of your code doesn't have to be hedged around with exception handling; secondly, if the "dangerous" actions are carefully split up into logical groups, you may be able to do exception handling on the method, not the actual actions. Stupid example:
my_list = get_list("one") # perfectly safe method
my_list.each do |x|
begin
x.dangerous_file_method() # dangerous method
rescue
x.status = 1
end
end