35

Possible Duplicate:
What does ||= mean in Ruby?

Forgive me if this is a newbie question but I'm reading a book on rails where the writer used this expression in a helper method:

@current_user ||= User.find_by_id(session[:user_id])

Is this use of double pipes still a Boolean OR statement?

If so how does it work?

mrdaliri
  • 7,148
  • 22
  • 73
  • 107
Daniel Upton
  • 5,561
  • 8
  • 41
  • 64

3 Answers3

60

It's a conditional assignment. From here:

 x = find_something() #=>nil
 x ||= "default"      #=>"default" : value of x will be replaced with "default", but only if x is nil or false
 x ||= "other"        #=>"default" : value of x is not replaced if it already is other than nil or false
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
19

The code foo ||= bar is almost equivalent to foo = foo || bar. In Ruby (as in many languages, like JavaScript or Io) boolean operators are "guard" operators. Instead of always returning true or false, they evaluate to the value of the first operand that evaluates to a "truthy" value.

For example, this code foo = 1 || delete_all_files_from_my_computer() will not delete anything: foo will be set to 1 and the second operand won't even be evaluated.

In Ruby, the only "non-truthy" values are nil and false. So the code foo ||= bar will only evaluate bar and set foo to the result if foo is nil or false.

As instance variables default to nil when not set, code like @foo ||= bar is a common Ruby idiom to set the instance variable if it has not already been set.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 3
    This is wrong. `foo ||= bar` is *somewhat* equivalent to `foo || foo = bar` and *not* `foo = foo || bar` (as has been discussed a dozen times on StackOverflow already, and about a million times on the Ruby mailinglists), but only somewhat. An *exact* expansion of `||=` has still not been found, and I personally am doubtful that `||=`'s semantics *can* even be expressed in Ruby *at all*. The clearest description I have seen so far of how `||=` works, is the evaluation algorithm given in the ISO Draft Ruby Language Specification, except that I am almost convinced that algorithm is *wrong*. – Jörg W Mittag Dec 21 '10 at 16:13
  • 1
    "I personally am doubtful that ||='s semantics can even be expressed in Ruby at all." It's probably either Bocce or the binary code of moisture evaporators. – the Tin Man Dec 21 '10 at 16:22
  • 2
    @JörgWMittag This is precisely why I wrote _"almost exactly equivalent"_ instead of _"equivalent"_ or _"the same as"_. For a newcomer who doesn't understand `||=`, the simple mental model that matches other `?=` compound assignment operators is sufficient. I have, nonetheless, removed the word _"exactly_" from my answer. – Phrogz Dec 21 '10 at 16:43
10

You can think of it as short for:

@current_user = @current_user || User.find_by_id(session[:user_id])

@current_user gets evaluated first, if it is non-null then the OR short-circuits, returning the value of @current_user, and not calling User.find_by_id.

(This works only because Ruby treats null as false, and non-null as true, in a boolean context. It doesn't work for languages like Java that don't treat non-booleans as truthy.)

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276