Error handling and exceptions

by msypniewski511 in Ruby for Rails

Ruby handles unacceptable behaviour at runtime
by raising an exception.

Raising and rescuing exception

An exception is a special kind of object, an instance of the class Exception or a
descendant of that class. Raising an exception means stopping normal execution
of the program and either dealing with the problem that’s been encountered or
exiting the program completely.

In Ruby, rescue is used within exception handling to capture and handle errors or exceptions
that occur during program execution. It allows you to specify code that should run in
case an exception occurs within a block of code.

Here's a basic example of how rescue works:

begin
  # Code that may raise an exception
  result = 10 / 0  # This will raise a ZeroDivisionError
rescue ZeroDivisionError => e
  # Code to handle the specific exception
  puts "An error occurred: #{e.message}"
end

Explanation:

The code within the begin block is executed.
If an exception occurs within the begin block, Ruby looks for a matching rescue block.
If a matching rescue block is found, the code within that block is executed, and then the program continues after the begin-rescue block.
In this example, result = 10 / 0 raises a ZeroDivisionError because division by zero is not allowed.
The rescue ZeroDivisionError => e block specifies that it should handle ZeroDivisionError exceptions. The => e part assigns the exception object to the variable e, which can then be used to access information about the exception, such as the error message.
Inside the rescue block, we print an error message using puts.
If an exception occurs that is not handled by any rescue block within the current scope, it will propagate up the call stack until it is either handled by an enclosing rescue block or it reaches the top level of the program, causing the program to terminate and display an error message.

print "Enter a number: "
n = gets.to_i
begin
  result = 100 / n
rescue
  puts "Your number didn't work. Was it zero???"
  exit
end
puts "100/#{n} is #{result}."

Raisng exceptions explicitly

In Ruby, you can raise exceptions explicitly using the raise keyword. Here's an example:

def validate_age(age)
  if age < 0
    raise ArgumentError, "Age cannot be negative"
  elsif age < 18
    raise ArgumentError, "You must be at least 18 years old"
  else
    puts "Age is valid"
  end
end

 # Example usage
begin
  validate_age(-5)
rescue ArgumentError => e
  puts "Error: #{e.message}"
end

Explanation:

  • The validate_age method takes an age parameter and checks if it's valid.
  • If the age is negative, it raises an ArgumentError with the message "Age cannot be negative".
  • If the age is less than 18, it raises an ArgumentError with the message "You must be at least 18 years old".
  • Otherwise, it prints "Age is valid".
  • In the example usage, validate_age(-5) is called, which raises an ArgumentError because the age is negative.
  • The rescue block catches the ArgumentError and prints its message. You can also raise exceptions without specifying a particular type: ruby raise "An error occurred" This will raise a generic RuntimeError with the given message "An error occurred". However, it's generally better practice to raise specific types of exceptions, like ArgumentError, RuntimeError, or custom exceptions, depending on the situation.

Creating your own exception classes

In Ruby, you can create your own exception classes by subclassing the built-in Exception class or one of its descendants like StandardError. Here's an example of creating a custom exception class:

class MyCustomError < StandardError
end

def some_method
  raise MyCustomError, "Something went wrong"
end

 # Example usage
begin
  some_method
rescue MyCustomError => e
  puts "Custom Error Caught: #{e.message}"
end

Explanation:

  • We define a custom exception class MyCustomError by subclassing StandardError.
  • Inside some_method, we raise an instance of MyCustomError with a descriptive error message.
  • In the example usage, we call some_method within a begin block.
  • If some_method raises a MyCustomError, the rescue block catches it, and we print the error message.

You can also add additional behaviour or attributes to your custom exception class as needed:

class MyCustomError < StandardError
  attr_reader :reason

  def initialize(reason)
    @reason = reason
    super("Custom Error: #{reason}")
  end
end

def some_method
  raise MyCustomError.new("Invalid input")
end

 # Example usage
begin
  some_method
rescue MyCustomError => e
  puts "Custom Error Caught: #{e.reason}"
end

In this example, MyCustomError has an additional attribute reason, and its constructor initializes both the message and the reason attribute. This allows more detailed information to be conveyed along with the exception.

0 Replies


Leave a replay

To replay you need to login. Don't have an account? Sign up for one.