What is the difference between Raising Exceptions vs Throwing Exceptions in Ruby?
I think http://hasno.info/ruby-gotchas-and-caveats has a decent explanation of the difference:
catch/throw are not the same as raise/rescue. catch/throw allows you to quickly exit blocks back to a point where a catch is defined for a specific symbol, raise rescue is the real exception handling stuff involving the Exception object.
What is the difference between `raise foo ` and `raise Exception.new( foo )`?
Technically, the first raises a RuntimeError with the message set to "foo"
, and the second raises an Exception with the message set to "foo"
.
Practically, there is a significant difference between when you would want to use the former and when you want to use the latter.
Simply put, you probably want a RuntimeError
not an Exception
. A rescue block without an argument will catch RuntimeErrors
, but will NOT catch Exception
s. So if you raise an Exception
in your code, this code will not catch it:
begin
rescue
end
In order to catch the Exception
you will have to do this:
begin
rescue Exception
end
This means that in a sense, an Exception
is a "worse" error than a RuntimeError
, because you have to do more work to recover from it.
So which you want depends on how your project does its error handling. For instance, in our daemons, the main loop has a blank rescue which will catch RuntimeErrors
, report them, and then continue. But in one or two circumstances, we want the daemon to really really die on an error, and in that case we raise an Exception
, which goes straight through our "normal error handling code" and out.
And again, if you are writing library code, you probably want a RuntimeError
, not an Exception
, as users of your library will be surprised if it raises errors that a blank rescue
block can't catch, and it will take them a moment to realize why.
Finally, I should say that the RuntimeError
is a subclass of the StandardError
class, and the actual rule is that although you can raise
any type of object, the blank rescue
will by default only catch anything that inherits from StandardError
. Everything else has to be specific.
C#: Do you raise or throw an exception?
In C# terminology, raising is used in the context of events and throwing is used in the context of exceptions.
Personally, I think throw/catch
combination is more beautiful than raise/catch
.
Raising an exception: use instance or class?
It makes no difference; the exception class will be instiantiated in either case.
If you provide a string, either as the argument to new
or as the second argument to raise
, it be passed to initialize
and will become the exception instance's .message
.
For example:
class GoatException < StandardError
def initialize(message)
puts "initializing with message: #{message}"
super
end
end
begin
raise GoatException.new "Goats do not enjoy origami." #--|
# | Equivilents
raise GoatException, "Goats do not enjoy origami." #--|
rescue Exception => e
puts "Goat exception! The class is '#{e.class}'. Message is '#{e.message}'"
end
If you comment the first raise
above, you'll see that:
- In both cases,
initialize
is called. - In both cases, the exception class is
GoatException
, notclass
as it would be if we were rescuing the exception class itself.
In Ruby what is the difference between different rescue statements?
Example:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
ensure
# ensure that this code always runs
end
Here, def
as a begin
statement:
def
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
ensure
# ensure that this code always runs
end
Basically there is no difference. In above code method def
can serve as a begin
statement:
As spickermann commented You can also use else
that is only run if there wasn't an expection
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
else
# Other exceptions
end
For each rescue
clause in the begin
block, Ruby compares the raised Exception against each of the parameters in turn. The match will succeed if the exception named in the rescue
clause is the same as the type of the currently thrown exception, or is a superclass of that exception. The code in an else
clause is executed if the code in the body of the begin statement runs to completion without exceptions. If an exception occurs, then the else
clause will obviously not be executed.
Refer this for more understanding: http://rubylearning.com/satishtalim/ruby_exceptions.html
Fail vs. raise in Ruby : Should we really believe the style guide?
use 'raise' for exceptions to be caught, and 'fail' for serious errors which are not meant to be handled
This is not what the official style guide or the link you provided say on the matter.
What is meant here is use raise
only in rescue
blocks. Aka use fail
when you want to say something is failing and use raise
when rethrowing an exception.
As for the "does it matter" part - it is not one of the most hardcore strictly followed rules, but you could make the same argument for any convention. You should follow in that order:
- Your project style guide
- Your company style guide
- The community style guide
Ideally, the three should be the same.
Update: As of this PR (December 2015), the convention is to always use raise
.
ruby catch-throw and efficiency
In addition to being the "correct" way to get out of control structures, catch-throw
is also significantly faster(10 times as fast in my testing). Check out this gist for my code and results.
What's the difference between raise, try, and assert?
Assert:
Used when you want to "stop" the script based on a certain condition and return something to help debug faster:
list_ = ["a","b","x"]
assert "x" in list_, "x is not in the list"
print("passed")
#>> prints passed
list_ = ["a","b","c"]
assert "x" in list_, "x is not in the list"
print("passed")
#>>
Traceback (most recent call last):
File "python", line 2, in <module>
AssertionError: x is not in the list
Raise:
Two reasons where this is useful:
1/ To be used with try and except blocks. Raise an error of your choosing, could be custom like below and doesn't stop the script if you pass
or continue
the script; or can be predefined errors raise ValueError()
class Custom_error(BaseException):
pass
try:
print("hello")
raise Custom_error
print("world")
except Custom_error:
print("found it not stopping now")
print("im outside")
>> hello
>> found it not stopping now
>> im outside
Noticed it didn't stop? We can stop it using just exit(1) in the except block.
2/ Raise can also be used to re-raise the current error to pass it up the stack to see if something else can handle it.
except SomeError, e:
if not can_handle(e):
raise
someone_take_care_of_it(e)
Try/Except blocks:
Does exactly what you think, tries something if an error comes up you catch it and deal with it however you like. No example since there's one above.
Why is it better to throw an exception rather than return an error code?
I've written about this at length: Exceptions vs. status returns, but briefly:
- Exceptions leaves your code clean of all the checks necessary when testing status returns on every call,
- Exceptions let you use the return value of functions for actual values,
- Exceptions can carry more information than a status return can,
- Most importantly: exceptions can't be ignored through inaction, while status returns can.
To expand on the last point: if you forget to do what you should be doing with status returns, you ignore errors. If you forget to do what you should be doing with exceptions, the exception bubbles up to the outer layer of the software where it becomes visible.
Related Topics
Rails 3 Disabling Session Cookies
Which Style of Ruby String Quoting Do You Favour
How to Display Ruby on Rails Form Validation Error Messages One At a Time
Difference Between Ruby and Ruby on Rails
How to Set Up the Database.Yml File in Rails
Find Key/Value Pairs Deep Inside a Hash Containing an Arbitrary Number of Nested Hashes and Arrays
How to Deal With the Sum of Rounded Percentage Not Being 100
Ruby Regular Expression to Match a Url
How to Clear the Terminal in Ruby
Ruby on Rails - Access Controller Variable from Model
Unzip (Zip, Tar, Tag.Gz) Files With Ruby