Lesson 2
Building an Address Book Application with Hashes
Introduction

Welcome! In this lesson, we’ll explore creating a simple address book application using Ruby hashes. This exercise will strengthen your understanding of hashes in Ruby, specifically in adding, retrieving, and deleting entries.

By the end of this lesson, you’ll have a solid grasp of these fundamental operations and how they’re applied in practical programming tasks.

Introducing Methods to Implement

In this task, we’ll build three core methods to manage our address book:

  1. add_contact(name, phone_number): Adds a new contact. If the contact already exists, it returns false and does not overwrite the number; otherwise, it adds the contact and returns true.
  2. get_contact(name): Retrieves the phone number for a given name. If the contact does not exist, it returns nil.
  3. delete_contact(name): Deletes a contact with the specified name. Returns true if the contact was successfully deleted and false if the contact does not exist.

Let’s walk through each method in detail.

Step 1: Implementing add_contact

This method will add a new contact with the given name and phone_number. If the contact already exists, it returns false; otherwise, it adds the contact and returns true.

Question: Why is it important to check if a contact already exists before adding?

Answer: To avoid duplicating contacts and prevent overwriting existing information, which can lead to data inconsistency.

Here’s how we implement this method:

Ruby
1class AddressBook 2 def initialize 3 @contacts = {} # Initialize an empty hash to store contacts 4 end 5 6 def add_contact(name, phone_number) 7 if @contacts.key?(name) # Check if contact already exists 8 return false 9 end 10 @contacts[name] = phone_number # Add new contact 11 true 12 end 13end 14 15# Example usage: 16address_book = AddressBook.new 17puts address_book.add_contact("Alice", "123-456-7890") # true 18puts address_book.add_contact("Alice", "098-765-4321") # false 19puts address_book.inspect # {"Alice"=>"123-456-7890"}

In this method:

  • We check if the contact already exists with if @contacts.key?(name).
  • If it exists, we return false.
  • If it doesn’t exist, we add it to the hash and return true.
Step 2: Implementing get_contact

This method retrieves the phone number associated with a specified name. If the contact doesn’t exist, it returns nil.

Question: Why return nil when a contact isn’t found?

Answer: Returning nil provides a clear indication that the contact isn’t in the address book, allowing for smooth error handling.

Here’s the implementation:

Ruby
1class AddressBook 2 def initialize 3 @contacts = {} # Initialize contacts hash 4 end 5 6 def add_contact(name, phone_number) 7 if @contacts.key?(name) 8 return false 9 end 10 @contacts[name] = phone_number 11 true 12 end 13 14 def get_contact(name) 15 @contacts[name] # Retrieve contact's phone number or return nil 16 end 17end 18 19# Example usage: 20address_book = AddressBook.new 21address_book.add_contact("Alice", "123-456-7890") 22puts address_book.get_contact("Alice") # '123-456-7890' 23puts address_book.get_contact("Bob") # nil

In this method:

  • We access the phone number with @contacts[name].
  • If the name doesn’t exist, it returns nil. There is no need to explicitly return nil as Ruby automatically handles it when a hash key is not found.
Step 3: Implementing delete_contact

This method deletes a contact by name. It returns true if the contact was deleted and false if the contact didn’t exist.

Question: What could happen if we try to delete a contact without checking if it exists?

Answer: Deleting a nonexistent contact might lead to errors or unintended behavior.

Here’s the method:

Ruby
1class AddressBook 2 def initialize 3 @contacts = {} 4 end 5 6 def add_contact(name, phone_number) 7 if @contacts.key?(name) 8 return false 9 end 10 @contacts[name] = phone_number 11 true 12 end 13 14 def get_contact(name) 15 @contacts[name] 16 end 17 18 def delete_contact(name) 19 if @contacts.key?(name) 20 @contacts.delete(name) # Remove contact if it exists 21 return true 22 end 23 false # Return false if contact was not found 24 end 25end

This concludes our implementation!

Example Usage for Address Book Methods

Below are some examples demonstrating how to use the methods in the AddressBook class:

Ruby
1# Creating a new address book 2address_book = AddressBook.new 3 4# Adding contacts 5puts address_book.add_contact("Alice", "123-456-7890") # true 6puts address_book.add_contact("Alice", "098-765-4321") # false 7puts address_book.add_contact("Bob", "987-654-3210") # true 8 9# Retrieving contacts 10puts address_book.get_contact("Alice") # '123-456-7890' 11puts address_book.get_contact("Charlie") # nil 12 13# Deleting contacts 14puts address_book.delete_contact("Alice") # true 15puts address_book.delete_contact("Charlie") # false 16 17# Inspecting the address book's state 18puts address_book.inspect # {"Bob"=>"987-654-3210"}

These examples show how to interact with the AddressBook methods, from adding and retrieving contacts to deleting them, providing a complete overview of the class functionality.

Why Hashes are Efficient for These Tasks

Hashes offer several advantages for managing an address book:

  • Efficient Lookups: Hashes provide average O(1) time complexity for lookups, making retrieving contacts by name very fast.
  • Uniqueness: Hashes inherently ensure that each key (contact name) is unique, simplifying data consistency.
  • Readability: The syntax for accessing hash entries is intuitive, making the code easier to understand and maintain.
  • Flexibility: Ruby hashes are versatile, allowing us to extend the address book to store additional information, such as email addresses or addresses, if needed in the future.
  • Handling Collisions: Although hash functions may generate the same hash for different keys, Ruby handles these collisions efficiently and ensures consistent performance. This is crucial for maintaining the integrity of our address book entries.

These features make Ruby hashes an ideal choice for implementing an address book.

Lesson Summary

In this lesson, we built a simple address book application using Ruby hashes. We implemented methods to add, retrieve, and delete contacts and discussed the benefits of using hashes for these operations.

You now have a practical understanding of how hashes work in Ruby and how to leverage them for efficient data management. Happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.