Ruby has the following operator available for conditional assignment:

x ||= y

Its meaning has been asked about so many times that some Ruby forums don't even bother to answer the question anymore. They collect others' answers and compile them into a page instead. But I think there's a reason that this question is asked so frequently. For one, the most commonly used explanations are vulnerable to edge cases and misinterpretation.

Explanation #1

Many pages claim that ||= is shorthand for:

x || x = y

That is, if x is falsy (nil or false), then it should be assigned the value of y.

It's a good explanation most of the time, but it doesn't hold for one very important edge case. When x is undefined, this "long form" explanation will raise a NameError while the "shorthand form" will assign y to x without failing.

Explanation #2

Other pages attempt to helpfully compare ||= to look-alike operators, e.g. +=. They say that the conditional assignment operator is expandable in the same way that this first line expands into the second:

x += y
x = x + y

But don't be fooled! This isn't the same! If it were, then ||= would expand to this:

x = x || y

However, this "expansion" always makes an assignment, even when it shouldn't. This is most noticeable when default values are involved. The below example shows how a hash map doesn't change size when ||= is used but grows when its "expansion" is:

hash ="default")
=> {}

hash[1] ||= "value"
=> "default"

=> {}

hash[2] = hash[2] || "value"
=> "default"

=> {2=>"default"}

Explanation #3

Here's a more human-readable explanation:

if x then x else x = y end

Similar to explanation #1, this explanation is vulnerable to the NameError for undefined x, but it's also easy to resolve with Ruby's defined? method.

The bigger issue is the assumption that x can be called repeatedly without modifying the program state. Unfortunately, it's impossible to know if x is a static value or a method that mutates other parts of the program every time it's called. With ||=, x is only ever called once.

This only-called-once behaviour is the reason that I rely heavily on ||= at all. Combined with a well-placed @variable, I use ||= in my Rails service objects to make API calls once and reuse the response repeatedly. And as a bonus, it's considered idiomatic Ruby!


With all these close-but-not-quite-right explanations, I wanted more. I wanted the true explanation to rule them all! I looked for a formal Ruby specification, but most links I found were outdated, non-existent, or missing information on the conditional assignment operator. Somewhat disappointing, but at least it provided insight into why so many close-but-not-quite-right explanations exist in the first place. Alas, my search continues.

In the meantime, these explanations are useful tools to have, so use them. Just beware that they're not perfect.