Ruby try &.
Safe navigation operator
Ruby 2.3.0 introduces new operator &.
which acts like object#try from ActiveSupport.
person = Person.new
puts "Money: #{person&.account&.money}"
Not so simple
You may guest that foo&.bar
is equivalent to (foo == nil) ? nil : foo.bar
. But it’s not.
def foo
obj = nil
(obj == nil) ? nil : obj.attr
end
foo += 1 # undefined method `+' for nil:NilClass
While using operator &.
you are safe.
obj = nil
obj&.attr += 1 # nil
The operator &.
checks for nil value and gracefully interrupts whole expression and return nil.
Using with Hashes
The same semantic for Hashes may looks like this
h = {key1: 1, key2: { subkey: 's'} }
p h[:key3]&.[](:subkey)
But it’s better to use dig
method since ruby 2.3
p h.dig :key3, :subkey
p h&.dig :key3, :subkey # even that safe
Attention
Some cases may lead to misunderstanding.
- The
&.
syntax only skips nil but recognizes false. It is not exactly equivalent to thes1 && s1.s2 && s1.s2.s3
syntax. The right interpretation isfoo&.bar (foo == nil) ? nil : foo.bar # almost the same, see above
- You should avoid using
nil?
check with&.
operator. It handles nil already and you may get unexpected resultnil&.nil? # => nil nil.nil? # => true
- The undefined variables are still undefined
obj&.attr # undefined local variable or method `obj' for main:Object obj = 1 obj&.attr # undefined method `attr' for 1:Integer