All programming languages work this way, but still it is nice to remember that Ruby does this.
>> n = nil
=> nil
>> x # x is undefined, just showing you that
NameError: undefined local variable or method `x’ for #
from (irb):6
>> (x || n.nil?) # x evaluates first, but since it’s undefined raises error
NameError: undefined local variable or method `x’ for #
from (irb):7
>> n.nil? || x # n.nil? is true, and so x never gets evaluated, thus not raising the error
=> true
=> nil
>> x # x is undefined, just showing you that
NameError: undefined local variable or method `x’ for #
from (irb):6
>> (x || n.nil?) # x evaluates first, but since it’s undefined raises error
NameError: undefined local variable or method `x’ for #
from (irb):7
>> n.nil? || x # n.nil? is true, and so x never gets evaluated, thus not raising the error
=> true
The same behavior works for the && (and) operator, of course it stops if it finds a false where as the || (or) operator stops when it finds a true (as you would expect).
>> ! @var.nil? && @var.a == “xyz”
=> false
>> @var.a == “xyz” && ! @var.nil?
NoMethodError: You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.a
from (irb):13
=> false
>> @var.a == “xyz” && ! @var.nil?
NoMethodError: You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.a
from (irb):13
So, this is most often useful for me when a variable that I need to check an attribute of might or might not be instantiated.
<% if ! @var.nil? && @var.a == "xyz" %>
The a attribute of your @var is xyz
<% end %>
The a attribute of your @var is xyz
<% end %>