I\'m just breaking into the ruby world and I could use a helping hand.
Suppose b
is nil
.
I\'d like the following code to return n
To use a safe_nils
similar to that you wrote:
def safe_nils &blk
return blk.call
rescue NoMethodError
return nil
end
safe_nils { a.b.c("d").e }
Remark in advance: b
is a method, not a variable. So b 'is' not nil, it returns nil.
When 'b' is a method, why not modify b, so it returns something, what can handle nil.
See below for an example.
You may define the missing methods:
class A
def b
nil
end
end
class NilClass
def c(p);nil;end
def e;nil;end
end
a = A.new
a.b.c("d").e
But I think, a rescue may fit your need better:
class A
def b
nil
end
end
a = A.new
x = begin a.c.c("d").e
rescue NoMethodError
nil
end
An example, how you may define a nil-like example.
class A
def b
MyNil.new
end
end
class MyNil
def method_missing(m, *args, &block)
if nil.respond_to?(m)
nil.send(m)
else
self
end
end
#Simulate nils bahaviour.
def nil?;true;end
def inspect;nil.inspect;end
def to_s;nil;end
end
a = A.new
x = a.b.c("d").e
p x
puts x
p x.nil?
One approach is to use inline assignment to local variables:
a && (ab = a.b) && (abcd = ab.c("d")) && abcd.e
For as long a chain as you've got here it isn't very elegant, but for a shorter chain it can be useful:
def date_updated(entry)
(updated = entry.updated) && updated.content
end
I think you can find a great solution in rails but that solution follows a different approach. Take a look at the try method. It's a clean approach.
Starting from ruby v2.3.0 there is another way built into the language, the safe navigation operator (&.)
You can write: a&.b&.c&.d
and you will safely get nil if one of the calls in the chain returns nil.
You can read more about it here:
http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
Check Ick's maybe
:
a.b.maybe.c("d").maybe.e
or using a block:
a.b.maybe { |b| b.c("d").e }