Ruby: Safe Navigation Operator to the Rescue

When developing a Ruby on Rails application that involves a user having one address, and the address table having all the address values such address_line_1, address_line_2, etc., the details may need to be shown similar to this:

1
<%= @user.address.address_line_1 %>

It can be easy to overlook the fact that this is not taking the address of the user as a registration step, but rather allowing the user to register, and after successful registration, to add details to their profile any time.

This can break the code when testing for a user that has no address. The error may look like this:

1
NoMethodError (undefined method `address_line_1' for nil:NilClass)

As a response to this:

1
<%= @user.address.address_line_1 %>

An expert solution to this issue is Safe Navigation Operator. Here is a working example:

Create an Application

Create a new Rails application.

1
2
rails new safe_navigation_operator
rails db:create

Generate Models

Generate two models, i.e. User and Address.

1
2
rails generate model user email
rails generate model address address_line_1

Add this line to db/migrate/abc_create_addresses.rb file:

1
t.belongs_to :user
1
rails db:migrate

Define Relationships

In user.rb, add this line:

1
has_one :address

In address.rb, add this line:

1
belongs_to :user, optional: true

Inserting Records

Now add some records in our database for the open rails console. Run rails console for your root folder.

1
2
3
4
5
User.create(email: 'test@gmail.com')

User.create(email: 'test_with_password@gmail.com', password: '123456')

u2.create_address(address_line_1: "Lahore")

Testing

1
2
3
4
5
u2.address.address_line_1
=> "Lahore"

u1.address.address_line_1
=> NoMethodError (undefined method `address_line_1' for nil:NilClass)

Solution

1
2
u1.address&.address_line_1
=> nil

This will handle the error efficiently and cleanly.