Learnerslesson
   JAVA   
  SPRING  
  SPRINGBOOT  
 HIBERNATE 
  HADOOP  
   HIVE   
   ALGORITHMS   
   PYTHON   
   GO   
   KOTLIN   
   C#   
   RUBY   
   C++   




RUBY - EXCEPTION HANDLING


Just imagine, you are asked to enter your gmail Id and Password to login to your Gmail account. But, by mistake you have entered a wrong password. And what if, Gmail exits without giving you a second chance to enter the Password? - It is not acceptable.


Same thing applies for any application. We are allowed to make some sort of mistakes. So that we get a second chance to rectify that. Such mistakes in Ruby are called as Exceptions.


So, the Exceptions should be handled/caught at runtime, and also the entire application should not close due to that Exception.


It is same as your Gmail account doesn't close when someone types a wrong password and at the same time Gmail needs to keep a track on how many times the user is entering a wrong Password.


Say for example, you have written a program to divide two numbers then add them. But by mistake, you tried to divide the number by zero.


Let us see what happens in the below example.


Example :



x = 3
y = 0
z = x / y
puts "The divided result is #{z}"
k = x + y
puts "The added result is #{k}"


Output :



  :in `/': divided by 0 (ZeroDivisionError)
     from add.rb:3:in `<main>'ZeroDivisionError: division by zero

So, if you see the above example, we have declared tow variables x and y and initialised 3 and 0 to them.


x = 3
y = 0

Then we tried dividing them,


z = x / y

And since, we tried to divide 3 by 0. It ended up with an error.


:in `/': divided by 0 (ZeroDivisionError)
	from add.rb:3:in `<main>'ZeroDivisionError: division by zero

That could be ok. But the problem is, the addition operation was not performed for the above error.


k = x + y
puts "The added result is #{k}"

And the program got halted. Which is not acceptable.


And Ruby provides a solution to the above problem, with something called as a begin - rescue block.


begin - rescue block to handle Exception


So, in the begin block, you can place the code if you suspect it might throw error.


And in the rescue block, you can handle the error. Only if there is an error, the rescue block executes.


Now, all you need to do is, place the division operation inside the blocks of begin. And if you want to display some message for that error, you can place the message in the rescue block.


Now, let's modify the above code using begin - rescue block.


Example :



x = 3
y = 0

begin
	z = x / y
	puts "The divided result is #{z}"
rescue
	puts "The division couldn't be performed due to an error."
end	

k = x + y
puts "The added result is #{k}"


Output :



  The division couldn't be performed due to an error.
  The added result is 3

Now, if you see the above output, it proceeded without any error. So, let us see how it worked.


So, in the above code, we have placed the division operation inside the begin block.


begin
	z = x / y
	puts "The divided result is #{z}"

And as usual an error occurred because we wanted to divide the number by 0.


And luckily, the begin block, handled the error. And the control comes to the rescue block.


rescue
	puts "The division couldn't be performed due to an error."
end

Note : Just remember, only if there is an error. The rescue block executes.

And prints the output.


The division couldn't be performed due to an error.

And most importantly, the addition operation didn't get halted. And the below line executes, adding two numbers.


k = x + y
puts "The added result is #{k}"

But let's say you have missed to assign value to a variable.


Example :



y = 0
z = x / y
puts "The divided result is #{z}"


Output :



  :in `<main>': undefined local variable or method `x' for main:Object (NameError)

In the above case, you forgot the define the value of x. And you ended up with the below Error.


undefined local variable or method 'x' for main:Object (NameError)

Now, just imagine, there could be two types of errors in one program. i.e. A ZeroDivisionError and a NameError.


To handle multiple errors, Ruby provides multiple rescue blocks, with one begin block.


begin with multiple rescue blocks to handle multiple Exceptions


Example :



y = 0
begin
	z = x / y
	puts "The divided result is #{z}"
rescue NameError
	puts "The division couldn't be performed as the variable is not defined."	
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
end	


Output :



  The division couldn't be performed as the variable is not defined.

Now, if you see the above output, the error message is more specific.


i.e. In the above program, we have forgot to define the value of x. And in Ruby it is called as NameError.


So, in the begin block,


begin
	z = x / y
	puts "The divided result is #{z}"

When Ruby tried to divide two numbers,


z = x / y

It finds the value of x is missing.


So, Ruby knows it is a NameError and goes to the rescue block with the name of the error as NameError.


And it finds one.


rescue NameError
	puts "The division couldn't be performed as the variable is not defined."

So, it prints the output,


The division couldn't be performed as the variable is not defined.

Note : The division error didn't occur, as the first number was absent.


Similarly, when there is a division error. The rescue block with ZeroDivisionError executes.


Example :



x = 3
y = 0
begin
	z = x / y
	puts "The divided result is ",z)
rescue NameError
	puts "The division couldn't be performed as the variable is not defined."	
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
end	


Output :



  The division couldn't be performed as the number was divided using zero.

Now, let us say, if there is no error. You want to display a message that there is no error.


And Ruby provides an else block for that.


begin - rescue with else block to handle Exception


If there is an error the rescue block is executed and if there is no error else block gets executed.


Example :



x = 3
y = 1
begin
	z = x / y
	puts "The divided result is #{z}"
rescue NameError
	puts "The division couldn't be performed as the variable is not defined."	
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
else 
	puts "There is no error"	
end	


Output :



  The divided result is 3
  There is no error

So, in the above program, there is no error. So, the else block got executed.


else
	puts "There is no error"

Printing, There is no error along with the divided result.

Output :



  The divided result is 3
  There is no error

Now, let us say the below program has a division error.


Example :



x = 3
y = 0
begin
	z = x / y
	puts "The divided result is #{z}"
rescue NameError
	puts "The division couldn't be performed as the variable is not defined."	
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
else 
	puts "There is no error"	
end	


Output :



  The division couldn't be performed as the number was divided using zero.

So, in the above program the else block did not get executed as there was an error.


Now, let us say, irrespective of any error. You want to display a message.


And Ruby provides a ensure block for that.


begin - rescue with ensure block to handle Exception


The ensure block gets executed irrespective of any error.


Let us see the below example, where there is no error.


Example :



x = 3
y = 1
begin
	z = x / y
	puts "The divided result is #{z}"
rescue NameError
	puts "The division couldn't be performed as the variable is not defined."	
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
ensure 
	puts "Begin block ended"	
end	


Output :



  The divided result is 3
  Begin block ended

So, in the above program, there is no error. And the finally block got executed.


ensure
	puts "Begin block ended"

Now, let us say the below program has a division error.


Example :



x = 3
y = 0
begin
	z = x / y
	puts "The divided result is ",z)
rescue ZeroDivisionError
	puts "The division couldn't be performed as the number was divided using zero."
ensure 
	puts "Begin block ended"
end		


Output :



  The division couldn't be performed as the number was divided using zero.
  Begin block ended

So, the ensure block gets executed, whether there is an error or not.