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.
- In the method
current_user?, iscurrent_usera variable or is it an invocation of the methodcurrent_user?
I don’t understand how to determine the value of current_user in this context.
- In the method
current_user,@current_useris 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.
- How come in
current_user=we use the@current_userbut incurrent_user?we just usecurrent_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.
It’s the method, since there’s no lexical of that name in scope.
It’s an instance variable of an instance of any class which has mixed-in module
SessionsHelper(typically withinclude SessionsHelper).sign_inis defined in this module along with a setter methodcurrent_user=.self.current_user = userwill send the message:current_user=with argumentusertoself. 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.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_usergetter in thecurrent_user?predicate we preserve the cache or fetch behaviour of the@current_user ||= User.find_by...expression in the getter.