Reputation: 13201
I'm working through the RoR tutorial by Michael Hartl. Here's some code from SessionsHelper:
module SessionsHelper
def sign_in(user)
cookies.permanent[:remember_token] = user.remember_token
self.current_user = user
end
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
def current_user?(user)
user == current_user
end
def signed_in?
!current_user.nil?
end
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
end
There are a number of things I don't understand from this code.
current_user?
, is current_user
a variable or is it an invocation of the method current_user
?I don't understand how to determine the value of current_user
in this context.
current_user
, @current_user
is an instance variable. What is it an instance variable of (i.e. what class?)?If you look under the sign_in(user)
method, you can see that self.current_user
is assigned the value of the object user
. But (assuming self is of the class UsersController because UsersController < ApplicationController
and in the definition of ApplicationController
there is a line that include SessionsHelper
) there is no definition of an instance variable current_user
for the self
object.
current_user=
we use the @current_user
but in current_user?
we just use current_user
?I've done h the prerequisite searching on StackOverflow but haven't found a good explanation for all these differences. A big part of what I'm trying to learn is when to use @current_user
, current_user
, :current_user
. I'm most familiar with C, C++, PHP, Java, JavaScript. If there are analogues to these languages, it would help me understand better what's going on.
Upvotes: 0
Views: 278
Reputation: 369526
Just to complement the other answers:
In the method
current_user
,@current_user
is an instance variable. What is it an instance variable of (i.e. what class?)?
Instance variables don't belong to classes. They belong to instances, that's why they are called instance variables. They always belong to self
, i.e. whichever object the receiver of the message is.
Instance variables spring into existence magically, the first time they are assigned, they aren't declared anywhere.
Upvotes: 2
Reputation: 43298
This is a basic concept in object-oriented programming called encapsulation. You have a variable @current_user
, but you don't use the variable directly. You use it through methods called getters and setters. Getters for getting the value of the variable en setters for setting the value of a variable.
In this case the getter method is current_user
and the setter method is current_user=
. Only inside the getter and setter you use the variable @current_user
directly. Outside those methods you always use the method call.
Upvotes: 1
Reputation: 20398
In the method current_user?, is current_user a variable or is it an invocation of the method current_user?
It's the method, since there's no lexical of that name in scope.
In the method current_user, @current_user is an instance variable. What is it an instance variable of (i.e. what class?)?
It's an instance variable of an instance of any class which has mixed-in module SessionsHelper
(typically with include SessionsHelper
).
If you look under the sign_in(user) method, you can see that self.current_user is assigned the value of the object user. But (assuming self is of the class UsersController because UsersController < ApplicationController and in the definition of ApplicationController there is a line that include SessionsHelper) there is no definition of an instance variable current_user for the self object.
sign_in
is defined in this module along with a setter method current_user=
. self.current_user = user
will send the message :current_user=
with argument user
to self
. Since sign_in came from this module it's quite likely that that message dispatch will go to the setter also defined in this module, though it's certainly possible that a setter of the same name may be defined by the class which included this module, or by a module included after this module, in which case those methods will be found first in the dispatch search.
How come in current_user= we use the @current_user but in current_user? we just use current_user?
It's considered good practise to limit direct instance variable access to the setter and getter methods (and sometimes the initialize) when they are defined. In this case, by reusing the current_user
getter in the current_user?
predicate we preserve the cache or fetch behaviour of the @current_user ||= User.find_by...
expression in the getter.
Upvotes: 2