Logical Operators
Bean Cart offers a discount when the customer has a loyalty card and the order is at least 5.00, or when it is the last hour before closing. Joining conditions like that is the job of the logical operators, and Ruby's versions have a useful twist: they return one of the actual values, not only true or false.
The rule
&&stops at the first falsy,||stops at the first truthy.
The three symbols:
&&reads as "and": true when both sides are truthy.||reads as "or": true when at least one side is truthy.!reads as "not": true when the value is falsy.
has_card = true
total = 6.0
last_hour = false
has_card && total >= 5 # => true
last_hour || total > 10 # => false
!last_hour # => trueBoth && and || short-circuit: they evaluate from left to right and stop as soon as the answer is known. And the result is the last value they looked at, not a converted boolean:
nil || "Guest" # => "Guest"
"Priya" || "Guest" # => "Priya"
nil && "Guest" # => nil
"Priya" && "Guest" # => "Guest"That makes || a neat way to supply a default: name = input_name || "Guest".
Short-circuiting also protects you. In order && order.size > 0, if order is nil, Ruby never calls order.size, so there is no error.
Ruby also has the words and, or and not. They look friendlier, but they bind more loosely than =, which causes surprises:
ok = true and false # ok is true! Read as: (ok = true) and false
ok = true && false # ok is falseUse &&, || and ! in conditions and assignments. Keep and and or for control flow, such as save or raise "failed", if you use them at all.
The shortcut
Walk left to right and stop at the first value that decides. For &&, the first falsy value decides, and it is the result; if none is falsy, the last value is the result. For ||, the first truthy value decides.
Group by precedence
&&binds tighter than||, so it reads:coupon || (has_card && total >= 5) || "no discount".
Drills
Answer fast — trust the rule.
What does nil || "Guest" return?
What does "Priya" && "Guest" return?
With order = nil, what does order && order.size > 0 do?
After ok = true and false, what is ok?
What is !0?
Remember
&&stops at the first falsy value,||at the first truthy one, and each returns the value it stopped on.- Walk left to right; the first deciding value is the answer. Use
x || defaultfor defaults. - Trap:
and,orandnotbind more loosely than=; use&&,||and!in expressions.
