Safe Navigation Operator
If you have worked in a Rails project, you have probably came across the try and try! methods. try saves us from checking conditions before drilling-down through a message chain. try! is more restrictive; it raises when the receiver does not respond to the method:
require "active_support"
require "active_support/core_ext/object/try"
User = Struct.new(:name)
users = [User.new("Jason")]
users.first.try(:name)
# "Jason"
users.first.try(:unknown_method)
# nil
users.first.try!(:unknown_method)
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">
Note these methods are provided by ActiveSupport. As of Ruby 2.3, this behaviour is now available in the language, called the safe navigation operator &.:
users = [User.new(name: "Jason")]
users.first&.name
# "Jason"
users = []
users.first&.name
# nil
Gotchas
When an object does not respond to a method, &. behaves like try!; it raises an error. However, nil seems to break this pattern:
# behaviour like try!
user&.unknown_method
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">
# given that
nil.nil?
# true
# this is confusing
nil&.nil?
# nil
The last example has a simple explanation: &. checks the receiver. Since the receiver is nil, &. immediately returns nil. It does not matter that nil responds to the message.
