[Talking-Ruby] The Safe Navigation Operator in Ruby 2.3.0 Release

The Safe Navigation Operator

In Ruby 2.3.0 Release, A safe navigation operator (so-called lonely operator) &., which already exists in C#, Groovy, and Swift, is introduced to ease nil handling as obj&.foo. Array#dig and Hash#dig are also added.

Safe Navigation Operator (&.) and Object#try method

The most interesting addition to Ruby 2.3.0 is the Safe Navigation Operator(&.).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Good
# Using the safe navigation operator (&.)
if account&.owner&.address
# ...
end

# Bad
if account && account.owner && account.owner.address
# ...
end

# Bad
# With #try method.
if account.try(:owner).try(:address)
# ...
end

Undefined method when &., Object#try, Object#try!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
account = Account.new(owner: Object.new)

account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>

account && account.owner && account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

# the try method doesn’t check if the receiver responds to the given method.
account.try(:owner).try(:address)
# => nil

# This is why it’s always better to use the stricter version of try - try!:
account.try!(:owner).try!(:address)
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

account&.owner&.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

Pitfalls

1
2
3
4
5
6
7
8
nil.nil?
# => true

nil?.nil?
# => false

nil&.nil?
# => nil

Array#dig and Hash#dig

Ruby 2.3 brings Array#dig and Hash#dig lets you easily traverse nested hashes, arrays, or even a mix of them. It returns nil if any intermediate value is missing.

1
2
3
4
5
6
7
8
9
10
11
12
x = {
foo: {
bar: [ 'a', { baz: 'x' } ]
}
}

# dig from hash.
x.dig(:foo, :bar) # => [ 'a', { baz: 'x' } ]

# dig from hash and embed array, hash.
x.dig(:foo, :bar, 1, :baz) # => "x"
x.dig(:foo, :wronk, 1, :baz) # => nil

References

[1] Ruby 2.3.0 Released - https://www.ruby-lang.org/en/news/2015/12/25/ruby-2-3-0-released/

[2] The Safe Navigation Operator (&.) in Ruby – Georgi Mitrev - https://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

[3] Ruby 2.3 brings Array#dig and Hash#dig - makandra dev - https://makandracards.com/makandra/41180-ruby-2-3-brings-array-dig-and-hash-dig