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 Exceptions. 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.