Ruby’s safe-navigation operator calls a method only when the receiver is not nil:
1 | account&.owner&.address |
It protects against nil; it does not protect against every invalid object.
1 | account = Struct.new(:owner).new(false) |
That behavior is useful. false is real data, not a missing value wearing a fake moustache.
&. versus ActiveSupport try
1 | nil&.unknown_method |
try is provided by ActiveSupport, not core Ruby. It returns nil when the receiver does not respond to the method. try! behaves more like &.: both tolerate a nil receiver but raise when a non-nil receiver lacks the method.
Prefer &. in ordinary Ruby code because it is language syntax, easier to read, and does not silently hide misspelled methods on non-nil objects.
Nested hashes
Use dig for nested hash or array access:
1 | payload = { |
This is clearer than:
1 | payload&.[](:user)&.[](:address)&.[](:city) |
Do not build a nil tunnel
A long chain such as:
1 | order&.customer&.profile&.address&.country&.code |
may be correct, but it can also hide an unclear domain contract. Ask which relationships are truly optional. If a customer must have a profile, silently returning nil may bury corrupted data instead of handling it.
Safe navigation is a precision tool. Using it everywhere because exceptions look unfriendly is how bugs become introverts.