Does Ruby have syntax for safe navigation operator of nil values, like in Groovy?
Asked Answered
G

4

23

In Groovy, there is a nice syntax for working with null values.

For example, I can do an if statement:

if (obj1?.obj2?.value) {

}

This will not throw a NullPointerException even if obj1 is null (it will evaluate to false).

This is something that's very convenient, so wondering if there is a Ruby equivalent I missed.

Griffis answered 22/6, 2012 at 20:56 Comment(3)
#8806082Oleneolenka
thanks! Also found the andand gem just now that tries to introduce this to ruby through a method: weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.htmlGriffis
Not yet in a stable release, but the development branch of Ruby now has the .? operator. See bugs.ruby-lang.org/issues/…Insomnia
D
26

In a rails app there is Object#try

So you can do

obj1.try(:obj2).try(:value)

or with a block (as said on comments bellow)

obj.try {|obj| obj.value}

UPDATE

In ruby 2.3 there is operator for this:

obj&.value&.foo

Which is the same as obj && obj.value && obj.value.foo

Decomposer answered 22/6, 2012 at 21:11 Comment(9)
Or alternately: obj.try {|obj| obj.value} - block mode often makes more visual sense IMHO.Harbird
This block syntax makes the most sense when you want to do something with the value like call a method on it.Hols
A common pattern to tackle this kind of problem are null objects.Rustle
Note that Object#try is a part of the ActiveSupport gem, which can also be used outside of Rails.Fewer
"Which is the same as"... This is not true when obj is false.Corbie
Thanks Jesse for the heads upDecomposer
@Decomposer I see this equivalency stated in every resource I can find about the new operator. I posted a new question regarding this misinformation: #34602554Corbie
[20] pry(main)> @asd.try(:asd) NoMethodError: undefined method try' for nil:NilClass`Brezin
@Brezin try is only available with ActiveSupport (part of Ruby on Rails)Decomposer
C
7

This has been added to Ruby 2.3.

The syntax is obj1&.meth1&.meth2.

Centipoise answered 23/10, 2015 at 16:55 Comment(0)
A
2

try was the only standard way to do this before Ruby 2.3. With Ruby 2.3 you can do:

if obj1&.obj2&.value

end

Also, if you have a hash structure, you can use the _. operator with Hashie:

require 'hashie'
myhash = Hashie::Mash.new({foo: {bar: "blah" }})

myhash.foo.bar
=> "blah"    

myhash.foo?
=> true

# use "underscore dot" for multi-level testing
myhash.foo_.bar?
=> true
myhash.foo_.huh_.what?
=> false
Anastassia answered 18/12, 2013 at 19:5 Comment(2)
So, try was the only way to do this when I answered the quesiton. The &. notation was just added with Ruby 2.3. The downvote wasn't really necessary, a comment or edit would have been appreciated.Anastassia
Not sure if your downvote was related, but I just made an edit because you were using JavaScript syntax for your if statement.Centipoise
G
2

Ruby 2.3 will have support for the safe navigation operator:

obj1&.obj2&.value

https://www.ruby-lang.org/en/news/2015/11/11/ruby-2-3-0-preview1-released/

Gillman answered 13/11, 2015 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.