November 30, 2015

As Ruby developers, we all come across situations when you have to deal with some uncertain values or methods in your code. And this happens:

foo && foo.bar && foo.bar.baz && foo.bar.baz.qux

It’s ugly, right? Well, if we are using Rails then we can fix the problem by simply rewriting it like this:


foo && foo.try(:bar).try(:baz).try(:qux)

This solutions\ is more elegant but still not ideal.
Well, all of you that suffered from this problem can now celebrate, as Ruby is getting it’s own safe navigation operator!
And it will look like this:

foo.?bar.?baz.?quz

This solution is small, easy and beautiful!
One thing to keep in mind though – it not an equivalent for try. .? First check to see if foo is not nil and only then call baz on it and further down the chain. Here’s a test right from Ruby Core code to demonstrate how it works. To rephrase a popular quote:

“A code is worth a thousand words”


def test_safe_call
s = Struct.new(:x, :y)
o = s.new("x")
assert_equal("X", o.x.?upcase)
assert_nil(o.y.?upcase)
assert_equal("x", o.x)
o.?x = 6
assert_equal(6, o.x)
o.?x *= 7
assert_equal(42, o.x)
end

Of course, that doesn’t mean that we all should go raving about, with this new operand all over our codebase. Using nil?, empty? and present? almost always point to a code smells and .? can also became the case. But at least we’ll have an elegant and idiomatic method in our Ruby toolbox when we need it.

And that’s a good thing!

P.S. Right now .? is available in Ruby 2.3.0-dev version. Unless something changes will see it soon. If not – Ruby 3.0 is best bet for sure.

BACK TO MAIN PAGE

Previous blogs

Successes and Failures in AI Build vs. Buy Decisions

April 10, 2024
Read more

Developing a Comprehensive AI Strategy for Competitive Advantage

Read more

Let’s Talk