agree with @Redithion in the comment
Safe Navigation Operator (&.) In Ruby
scenario
Imagine that you have an account which has an owner and you want to get the address owner. If you want to be safe and not risk the Nil error, write something like the following.
if account && account.owner && account.owner.address ... end
It is really verbose and annoying to type. ActiveSupport includes a try method that has similar behavior (but with a few key differences that will be discussed later):
if account.try(:owner).try(:address) ... end
It does the same - returns either the address or nil if some value in the chain is nil . The first example can also return false if, for example, owner set to false.
Via &.
We can rewrite the previous example using the safe navigation operator :
account&.owner&.address
More examples
Let's compare all three approaches in more detail.
account = Account.new(owner: nil)
So far no surprises. What if owner false (unlikely, but not impossible in the exciting world of shitty code)?
account = Account.new(owner: false) account.owner.address # => NoMethodError: undefined method 'address' for false:FalseClass ' account && account.owner && account.owner.address # => false account.try(:owner).try(:address) # => nil account&.owner&.address # => undefined method 'address' for false:FalseClass'
Here comes the first surprise - &. the syntax skips only nil but recognizes false! This is not exactly equivalent to the syntax s1 && s1.s2 && s1.s2.s3 .
What if the owner is present but not responding to address ?
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>' account.try(:owner).try(:address) # => nil account&.owner&.address # => NoMethodError: undefined method 'address' for #<Object:0x00559996b5bde8>'
the example below is confusing and nil&.nil? should return true .
Be careful when using &. operator and checking for nil values. Consider the following example:
nil.nil?