What does the following code mean in Ruby?

||=

Does it have any meaning or reason for the syntax?

18 Answers 11

It means or-equals to. It checks to see if the value on the left is defined, then use that. If it's not, use the value on the right. You can use it in Rails to cache instance variables in models.

A quick Rails-based example, where we create a function to fetch the currently logged in user:

class User > ActiveRecord::Base

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

end

It checks to see if the @current_user instance variable is set. If it is, it will return it, thereby saving a database call. If it's not set however, we make the call and then set the @current_user variable to that. It's a really simple caching technique but is great for when you're fetching the same instance variable across the application multiple times.

8 upvote
  flag
This is wrong. Please read Ruby-Forum.Com/topic/151660 and the links provided therein. – Jörg W Mittag
1 upvote
  flag
@Jo(umlaut)rg, I'm not seeing what is wrong about it. Your link is a list of other links. No real explanation why it's wrong, just sounds like a value judgment on your end. – eggmatters
upvote
  flag
best answer in thread! – Stef Hej
upvote
  flag
this answer is wrong, because it not only triggers on undefined, but also on false and nil, which might not be relevant for current_user, but especially the false can be unexpectecd in other cases – dfherr
up vote 142 down vote accepted

This question has been discussed so often on the Ruby mailing-lists and Ruby blogs that there are now even threads on the Ruby mailing-list whose only purpose is to collect links to all the other threads on the Ruby mailing-list that discuss this issue.

Here's one: The definitive list of ||= (OR Equal) threads and pages

If you really want to know what is going on, take a look at Section 11.3.1.2 "Abbreviated assignments" of the Ruby Language Draft Specification.

As a first approximation,

a ||= b

is equivalent to

a || a = b

and not equivalent to

a = a || b

However, that is only a first approximation, especially if a is undefined. The semantics also differ depending on whether it is a simple variable assignment, a method assignment or an indexing assignment:

a    ||= b
a.c  ||= b
a[c] ||= b

are all treated differently.

1 upvote
  flag
The second link has suffered from bit rot (comment from meta by //allinonescript.com/users/540162/nightfirecat). – Andrew Grimm
191 upvote
  flag
That's a very cryptic non-answer. The short answer seems to be: a ||= b means, if a is undefined then assign it the value of b, otherwise leave it alone. (Ok, there are nuances and special cases, but that's the basic case.) – Steve Bennett ㄹ
16 upvote
  flag
@SteveBennett: I wouldn't call the fact that a = false; a ||= true does not do what your answer says it does a "nuance". – Jörg W Mittag
upvote
  flag
Thanks @SteveBennett! – Yavin4
9 upvote
  flag
Maybe this question has been asked so many times because people keep responding that this question has been asked so many times. – einnocent
upvote
  flag
why a ||= b is a equivalent to a || a = b if its have different behavior: a ||= 10 #=> 10 a = a || 10 #=> 10 a || a = 10 #=> NameError: undefined local variable or method 'a' for main:Object ? It depends on the Ruby version? – bondarenko.dev
upvote
  flag
@bondarenko.dev: it is not equivalent, and I never said it was. I explicitly said it is only an approximation, and that behavior differs especially if a is undefined. – Jörg W Mittag
4 upvote
  flag
With this answer is easy to see why there are multiple threads. If you try to search for an answer to this question using a novice hat, you will notice that all answers are not clear. For example, with this one you are just saying what is not. I suggest to improve your answer and give a easy answers for novices: a = b unless a – Arnold Roa
1 upvote
  flag
Not a good answer at all. Not sure why this was accepted. It barely tries to explain what ||= is, instead tries to point someone to another thread (which is ironic because you're trying to end this chase). Why not just say it straight up what it is? I'm sure it would have spared both you and the reader more work. Downvoted. – theGreenCabbage
upvote
  flag
Very lacking answer. You didn't explain what does it do – Yehonatan
upvote
  flag
for ruby newbie, they may don't know a || a = b either. Better to at lease give an example and say what is the result. Otherwise, you are just introducing another question instead of answering – Steve

a ||= b is a "conditional assignment operator". It is sort-of-but-not-quite(*) shorthand for a || a = b.

It means "if a is undefined or falsey (false or nil), then evaluate b and set a to the result".

For example:

> a ||= nil
=> nil
> a ||= 0;
=> 0
> a ||= 2;
=> 0

> foo = false;
=> false
> foo ||= true;
=> true
> foo ||= false;
=> true

Ruby's short circuit evaluation means that if a is defined and evaluates to true, then the right hand side of the operator is not evaluated, and no assignment takes place. This distinction is unimportant if a and b are both local variables, but is significant if either is a getter/setter method of a class.

Confusingly, it looks similar to other assignment operators (such as +=) but behaves differently.

a += b   translates to   a = a + b

a ||= b   roughly translates to*    a || a = b

*Except that, when a is undefined, a || a = b would be NameError, whereas a ||= b sets a to b.

Further reading:

36 upvote
  flag
Thank you for this answer, it make much more sense. – Tom Hert
8 upvote
  flag
Best answer given! Thanks man! – JGutierrezC
10 upvote
  flag
This trumps the accepted answer. Thanks. – Adam Waite
upvote
  flag
havent searched enough but still dont get why you would use this as opposed to a = a || b. maybe just my personal opinion but a little ridiculous that such a nuance exists... – dtc
2 upvote
  flag
@dtc, consider h = Hash.new(0); h[1] ||= 2. Now consider the two possible expansions h[1] = h[1] || 2 vs h[1] || h[1] = 2. Both expressions evaluate to 0 but the first unnecessarily increases the size of the hash. Perhaps that's why Matz chose to make ||= behave more like the second expansion. (I based this on an example from one of the threads linked to in another answer.) – antinome
1 upvote
  flag
I like the other answer for how in-depth it goes, but I love this answer for it's simplicity.For someone learning Ruby, this is the type of answer we need. If we knew what ||= meant, then the question would probably have been worded differently. – OBCENEIKON
1 upvote
  flag
Fyi, a || a = b raises a NameError if a is undefined. a ||= b does not, but instead initializes a and sets it to b. That's the only distinction between the two as far as I know. Similarly, the only difference between a = a || b and a ||= b that I'm aware of is that if a= is a method, it will get called regardless of what a returns. Also, the only difference between a = b unless a and a ||= b that I'm aware of is that that statement evaluates to nil instead of a if a is truthy. Lots of approximations, but nothing quite equivalent... – Ajedi32
upvote
  flag
Much better than the accepted answer. – Adam
upvote
  flag
please take a look at comment under question – Muhammad Umer
upvote
  flag
Yep, that's addressed under the "Sort of but not quite". – Steve Bennett ㄹ
x ||= y

is

x || x = y

"if x is false or undefined, then x point to y"

a ||= b

is equivalent to

a || a = b

and not

a = a || b

because of the situation where you define a hash with a default (the hash will return the default for any undefined keys)

a = Hash.new(true) #Which is: {}

if you use:

a[10] ||= 10 #same as a[10] || a[10] = 10

a is still:

{}

but when you write it like so:

a[10] = a[10] || 10

a becomes:

{10 => true}

because you've assigned the value of itself at key 10, which defaults to true, so now the hash is defined for the key 10, rather than never performing the assignment in the first place.

Suppose a = 2 and b = 3

THEN, a ||= b will be resulted to a's value i.e. 2.

As when a evaluates to some value not resulted to false or nil.. That's why it ll not evaluate b's value.

Now Suppose a = nil and b = 3.

Then a ||= b will be resulted to 3 i.e. b's value.

As it first try to evaluates a's value which resulted to nil.. so it evaluated b's value.

The best example used in ror app is :

#To get currently logged in iser
def current_user
  @current_user ||= User.find_by_id(session[:user_id])
end

# Make current_user available in templates as a helper
helper_method :current_user

Where, User.find_by_id(session[:user_id]) is fired if and only if @current_user is not initialized before.

upvote
  flag
Such type of explanation works? :-) – Pankhuri
upvote
  flag
merging and deleting the other one done.. :-) – Pankhuri

Concise and complete answer

a ||= b

evaluates the same way as each of the following lines

a || a = b
a ? a : a = b
if a then a else a = b end

-

On the other hand,

a = a || b

evaluates the same way as each of the following lines

a = a ? a : b
if a then a = a else a = b end

-

Edit: As AJedi32 pointed out in the comments, this only holds true if: 1. a is a defined variable. 2. Evaluating a one time and two times does not result in a difference in program or system state.

upvote
  flag
are you certain? This implies that if a is false/zero/undefined, it is evaluated twice. (But I don't know Ruby, so I don't know if lvalues can be 'evaluated' exactly...) – Steve Bennett ㄹ
upvote
  flag
I see what you're saying. What I meant by two lines being equivalent is that the end state will be equivalent after the whole line has been evaluated, meaning the value of a, b and what is returned. Whether or not ruby interpreters use different states - like several evaluations of a - to get there is entirely possible. Any ruby interpreter experts out there? – the_minted
1 upvote
  flag
This isn't quite right. a || a = b, a ? a : a = b, if a then a else a = b end, and if a then a = a else a = b end will throw an error if a is undefined, whereas a ||= b and a = a || b will not. Also, a || a = b, a ? a : a = b, if a then a else a = b end, a = a ? a : b, and if a then a = a else a = b end evaluate a twice when a is truthy, whereas a ||= b and a = a || b do not. – Ajedi32
1 upvote
  flag
*correction: a || a = b will not evaluate a twice when a is true. – Ajedi32
1 upvote
  flag
@the_minted the end state will be equivalent after the whole line has been evaluated That's not necessarily true though. What if a is a method? Methods can have side effects. E.g. With public; def a=n; @a=n; end; def a; @a+=1; end; self.a = 5, self.a ||= b will return 6, but self.a ? self.a : self.a = b will return 7. – Ajedi32
upvote
  flag
@the_minted this only holds true if: 1. a is a defined variable So this is definitely not equivalent. – Xavier Nayrac
upvote
  flag
@XavierNayrac Updated to say evaluates in the same way rather than equals. – the_minted

It's like lazy instantiation. If the variable is already defined it will take that value instead of creating the value again.

In short, a||=b means: If a is undefined, nil or false, assign b to a. Otherwise, keep a intact.

This is the default assignment notation

for example: x ||= 1
this will check to see if x is nil or not. If x is indeed nil it will then assign it that new value (1 in our example)

more explicit:
if x == nil
x = 1
end

To be precise, a ||= b means "if a is undefined or falsy (false or nil), set a to b and evaluate to (i.e. return) b, otherwise evaluate to a".

Others often try to illustrate this by saying that a ||= b is equivalent to a || a = b or a = a || b. These equivalencies can be helpful for understanding the concept, but be aware that they are not accurate under all conditions. Allow me to explain:

  • a ||= ba || a = b?

    The behavior of these statements differs when a is an undefined local variable. In that case, a ||= b will set a to b (and evaluate to b), whereas a || a = b will raise NameError: undefined local variable or method 'a' for main:Object.

  • a ||= ba = a || b?

    The equivalency of these statements are often assumed, since a similar equivalence is true for other abbreviated assignment operators (i.e. +=,-=,*=,/=,%=,**=,&=,|=,^=,<<=, and >>=). However, for ||= the behavior of these statements may differ when a= is a method on an object and a is truthy. In that case, a ||= b will do nothing (other than evaluate to a), whereas a = a || b will call a=(a) on a's receiver. As others have pointed out, this can make a difference when calling a=a has side effects, such as adding keys to a hash.

  • a ||= ba = b unless a??

    The behavior of these statements differs only in what they evaluate to when a is truthy. In that case, a = b unless a will evaluate to nil (though a will still not be set, as expected), whereas a ||= b will evaluate to a.

  • a ||= bdefined?(a) ? (a || a = b) : (a = b)????

    Still no. These statements can differ when a method_missing method exists which returns a truthy value for a. In this case, a ||= b will evaluate to whatever method_missing returns, and not attempt to set a, whereas defined?(a) ? (a || a = b) : (a = b) will set a to b and evaluate to b.

Okay, okay, so what is a ||= b equivalent to? Is there a way to express this in Ruby?

Well, assuming that I'm not overlooking anything, I believe a ||= b is functionally equivalent to... (drumroll)

begin
  a = nil if false
  a || a = b
end

Hold on! Isn't that just the first example with a noop before it? Well, not quite. Remember how I said before that a ||= b is only not equivalent to a || a = b when a is an undefined local variable? Well, a = nil if false ensures that a is never undefined, even though that line is never executed. Local variables in Ruby are lexically scoped.

upvote
  flag
So your extended third example: (a=b unless a) or a – vol7ron
upvote
  flag
@vol7ron That has a similar problem as #2. If a is a method, it will be called twice instead of once (if it returns a truthy value the first time). That could cause behaviors to differ if, for example, a takes a long time to return or has side effects. – Ajedi32
upvote
  flag
Also, first sentence, shouldn't it say assign b to a, doesn't the rhs still assign to the lhs, or in other words, doesn't the lhs still set its value to the rhs? – vol7ron
1 upvote
  flag
@vol7ron Fixed. Is that more clear? – Ajedi32
upvote
  flag
Best a ||= b answer I've found on the Internet. Thanks. – Eric Duminil
irb(main):001:0> a = 1
=> 1
irb(main):002:0> a ||= 2
=> 1

Because a was already set to 1

irb(main):003:0> a = nil
=> nil
irb(main):004:0> a ||= 2
=> 2

Because a was nil

upvote
  flag
What is the answered date here. Why it is not showing year? – Shiv
upvote
  flag
@Shiv: It's magic. – fuzz

Please also remember that ||= isn't an atomic operation and so, it isn't thread safe. As rule of thumb, don't use it for class methods.

unless x x = y end

unless x has a value (it's not nil or false), set it equal to y

is equivalent to

x ||= y

Basically,


x ||= y means

if x has any value leave it alone and do not change the value, otherwise set x to y.

as a common misconception a||=b is not equivalent to a = a||b but it is but it behaves like a || a = b

But here comes a tricky case

If a is not defined, a || a = 42 raises NameError, while a ||= 42 returns 42. So, they don't seem to be equivalent expressions.

b = 5
a ||= b

This translates to:

a = a || b

which will be

a = nil || 5

so finally

a = 5

Now if you call this again:

a ||= b
a = a || b
a = 5 || 5
a = 5

b = 6

Now if you call this again:

a ||= b
a = a || b
a = 5 || 6
a = 5 

If you observe, b value will not be assigned to a. a will still have 5.

Its a Memoization Pattern that is being used in Ruby to speed up accessors.

def users
  @users ||= User.all
end

This basically translates to:

@users = @users || User.all

So you will make a call to database for the first time you call this method.

Future calls to this method will just return the value of @users instance variable.

||= is called a conditional assignment operator.

It basically works as = but with the exception that if a variable has already been assigned it will do nothing.

First example:

x ||= 10

Second example:

x = 20
x ||= 10

In the first example x is now equal to 10. However, in the second example x is already defined as 20. So the conditional operator has no effect. x is still 20 after running x ||= 10.

Not the answer you're looking for? Browse other questions tagged or ask your own question.