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.
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 ||= b ⇔ a || 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 ||= b ⇔ a = 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 ||= b ⇔ a = 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 ||= b ⇔ defined?(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 isa ||= 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.
x ||= y
meansif
x
has any value leave it alone and do not change the value, otherwise setx
toy
.Suppose
a = 2
andb = 3
THEN,
a ||= b
will be resulted toa
's value i.e.2
.As when a evaluates to some value not resulted to
false
ornil
.. That's why itll
not evaluateb
's value.Now Suppose
a = nil
andb = 3
.Then
a ||= b
will be resulted to3
i.e.b
's value.As it first try to evaluates a's value which resulted to
nil
.. so it evaluatedb
's value.The best example used in ror app is :
Where,
User.find_by_id(session[:user_id])
is fired if and only if@current_user
is not initialized before.It's like lazy instantiation. If the variable is already defined it will take that value instead of creating the value again.
To be precise,
a ||= b
means "ifa
is undefined or falsy (false
ornil
), seta
tob
and evaluate to (i.e. return)b
, otherwise evaluate toa
".Others often try to illustrate this by saying that
a ||= b
is equivalent toa || a = b
ora = 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 ||= b
⇔a || a = b
?The behavior of these statements differs when
a
is an undefined local variable. In that case,a ||= b
will seta
tob
(and evaluate tob
), whereasa || a = b
will raiseNameError: undefined local variable or method 'a' for main:Object
.a ||= b
⇔a = 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 whena=
is a method on an object anda
is truthy. In that case,a ||= b
will do nothing (other than evaluate toa
), whereasa = a || b
will calla=(a)
ona
's receiver. As others have pointed out, this can make a difference when callinga=a
has side effects, such as adding keys to a hash.a ||= b
⇔a = 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 tonil
(thougha
will still not be set, as expected), whereasa ||= b
will evaluate toa
.a ||= b
⇔defined?(a) ? (a || a = b) : (a = b)
????Still no. These statements can differ when a
method_missing
method exists which returns a truthy value fora
. In this case,a ||= b
will evaluate to whatevermethod_missing
returns, and not attempt to seta
, whereasdefined?(a) ? (a || a = b) : (a = b)
will seta
tob
and evaluate tob
.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)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 toa || a = b
whena
is an undefined local variable? Well,a = nil if false
ensures thata
is never undefined, even though that line is never executed. Local variables in Ruby are lexically scoped.||= is a conditional assignment operator
is equivalent to
or alternatively
This translates to:
which will be
so finally
Now if you call this again:
Now if you call this again:
If you observe,
b
value will not be assigned toa
.a
will still have5
.Its a Memoization Pattern that is being used in Ruby to speed up accessors.
This basically translates to:
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.