Safe navigation calls a method only when the receiver is not nil.

safe navigation The `&.` operator returns `nil` instead of calling a method on `nil`.

Safe Navigation

user_key
safe_navigation.rb
Replay: real traced execution (multi-file project)
user_key = :ada
users = {
  ada: { name: "Ada", email: "ada@example.com" },
  grace: { name: "Grace", email: nil }
}

user = users[user_key]
email = user&.dig(:email) || "no email"
name = user&.dig(:name) || "unknown"

puts "key=#{user_key}"
puts "name=#{name}"
puts "email=#{email}"
user_key = :grace
users = {
  ada: { name: "Ada", email: "ada@example.com" },
  grace: { name: "Grace", email: nil }
}

user = users[user_key]
email = user&.dig(:email) || "no email"
name = user&.dig(:name) || "unknown"

puts "key=#{user_key}"
puts "name=#{name}"
puts "email=#{email}"
user_key = :missing
users = {
  ada: { name: "Ada", email: "ada@example.com" },
  grace: { name: "Grace", email: nil }
}

user = users[user_key]
email = user&.dig(:email) || "no email"
name = user&.dig(:name) || "unknown"

puts "key=#{user_key}"
puts "name=#{name}"
puts "email=#{email}"
  1. user_key ← ada, users ← {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}}

    1user_key→ ada = :ada  #@user_key=:grace, :missing2users→ {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}} = {3  ada: { name: "Ada", email: "ada@example.com" },4  grace: { name: "Grace", email: nil }5}67user→ {:name=>"Ada", :email=>"ada@example.com"} = users[user_key]{:name=>"Ada", :email=>"ada@example.com"}8email→ ada@example.com = user&.dig(:email)ada@example.com || "no email"9name→ Ada = user&.dig(:name)Ada || "unknown"1011puts "key=#{user_keyada}"12puts "name=#{nameAda}"13puts "email=#{emailada@example.com}"
    outputkey=ada
    name=Ada
    email=ada@example.com
  1. user_key ← grace, users ← {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}}

    1user_key→ grace = :grace2users→ {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}} = {3  ada: { name: "Ada", email: "ada@example.com" },4  grace: { name: "Grace", email: nil }5}67user→ {:name=>"Grace", :email=>nil} = users[user_key]{:name=>"Grace", :email=>nil}8email→ no email = user&.dig(:email)(empty) || "no email"9name→ Grace = user&.dig(:name)Grace || "unknown"1011puts "key=#{user_keygrace}"12puts "name=#{nameGrace}"13puts "email=#{emailno email}"
    outputkey=grace
    name=Grace
    email=no email
  1. user_key ← missing, users ← {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}}

    1user_key→ missing = :missing2users→ {:ada=>{:name=>"Ada", :email=>"ada@example.com"}, :grace=>{:name=>"Grace", :email=>nil}} = {3  ada: { name: "Ada", email: "ada@example.com" },4  grace: { name: "Grace", email: nil }5}67user→ (empty) = users[user_key](empty)8email→ no email = user&.dig(:email)(empty) || "no email"9name→ unknown = user&.dig(:name)(empty) || "unknown"1011puts "key=#{user_keymissing}"12puts "name=#{nameunknown}"13puts "email=#{emailno email}"
    outputkey=missing
    name=unknown
    email=no email