I'm following the pretty great SLite & Ruby tutorial over at ZetCode and have run into a silly question. What exactly is going on here?
rescue SQLite3::Exception => e
puts "Exception occured"
puts e
I conceptually get what's happening: if an exception is raised, it gets printed on the screen. But what is this syntax, specifically?
SQLite3::Exception => e
Is there another simple example of where I'd use the hash rocket like this?
Thanks!
The rescue statement has an unusual use for that notation. It means "capture the exception of type SQLite3::Exception into the variable e":
rescue SQLite3::Exception => e
You're not required to capture the exception into a variable, you can omit that part if you don't need it, and you don't need to specify the exception kind, either, which will default to the exception base class Exception.
The syntax is only coincidentally the same as the hash declaration presumably to promote consistency. The two are not otherwise related.
Related
So, for hashes in Ruby you can use hashrockets like this:
corned_beef = {
:ingredient1 => "beef",
:ingredient2 => "potatoes"
}
or the more concise json-ish style.
corned_beef = {
ingredient1: "beef",
ingredient2: "potatoes"
}
Is there a json-ish styled way to catch Ruby exceptions? The normal way is this:
begin
# ...blah blah...
rescue ActiveRecord::RecordNotFound => e
logger.debug { "Where's da beef?" }
rescue => e
logger.debug { "#{e.message}\nBacktrace Begin:\n #
{e.backtrace.join("\n")}" }
else
# ...blah blah...
end
I've started to hate seeing hashrockets in my code, even for this. Someone please educated me.
EDIT:
For some reason, this has attracted comments from the kind of people who have code-religious arrogant condescending judgement. This is a forum for questions, if you don't like the question, kindly close your window. Ruby was optimized for programmer happiness. My question is seeking what I deem cleaner sexier code. What is not wanted is an expression of lots of opinions that do nothing toward helping achieve an answer. I am a good programmer with legacy code that has been in production serving billions and is probably older than most of you. Please stop shoveling pointless opinions if it doesn't answer the question. So far, it doesn't look like what I'm seeking exists. That's fine.
If you absolutely want to get rid of it, you can fall back to some of Ruby's Global Variables, specifically
$!
The exception information message set by 'raise'.
$#
Array of backtrace of the last exception thrown.
begin
raise ArgumentError, 'Your argument is invalid'
rescue ArgumentError
puts "#{$!.message}\nBacktrace Begin:\n#{$#.join("\n")}"
# or
puts "#{$!.message}\nBacktrace Begin:\n#{$!.backtrace.join("\n")}"
end
I've never used any of the globals in an any real applications, so not sure what type of things you might want to watch out for (if multiple threads throwing different errors simultaneously* might be an issue, for example).
No, AFAIK this is the syntax required for creating a reference to the caught exception.
I get some unexpected errors on occasion such as timeout errors, 503 errors, etc. There are errors that I don't even know about that I may receive. I can't account for all of them by doing something like:
rescue Timeout::Error => e
It's also a terrible idea to rescue Exception.
What is an alternative that I could use? I want my code to rescue all of them when there is an error; if there is no error, I need it to be avoided. I want to be able to kill my script but not skip over syntax errors, etc.
You can rescue for StandardError, or simply rescue, which are the same:
rescue StandardError => e
# or
rescue => e
You can see in the following table which exceptions are rescued from StandardError - Note that they are a subset from Exception, and conceitually should be errors that are OK to be catch.
Of course you can have gems that defines exception in the wrong place, but this should not happen in well-developed gems.
(source: rubylearning.com)
I personally like to rescue only exceptions I know how to handle, except when it is to add in a log/backtrace system to consult the errors later. If this is the case, I usually rescue StandardError
I am having trouble understanding ruby exceptions and what happens after an exception occurs.
When an exception happens, and I rescue it, do the commands after the exception still get executed, or does it skip them and jump to the rescue? If I want it to do the stuff after the exception what can I do? Thanks!
In the following example:
begin
var = "string"
var.do_someting to raise exception
var.do_something_else
var.do_something_else_again
rescue => e
puts "error was #{e}"
end
It halts and jumps straight to rescue. If there's stuff that must run no matter what, ensure is probably what you want.
Begin, Rescue and Ensure in Ruby?
http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html
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.