I am going through the great Michael Hartl tutorial to build ruby app here.
I am trying to understand the concept of how to create a session and I am stuck in understanding this line:
self.current_user = user
in this method:
module SessionsHelper
def sign_in(user)
cookies.permanent[:remember_token] = user.remember_token
self.current_user = user
end
end
I understand the whole concept of creating a cookie with the user_token.
But I don’t understand what does self.current_user = user means and why is it even necessary to keep this line of code – I have the cookie with the token – why do I need to know the current user?
Also, where does this “self” is being stored – it is not like a flash[:success] parameter I can see in one of my views. so I don’t understand where it is.
there are also these 2 methods in the same module:
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
And still I am trying to connect the dots of the purpose for this mysterious current user – is its purpose is to create @current_user global variable to use in the views?
If so – why there are there these 2 duplicated functions def current_user=(user) and def current_user
A few things.
First, you’re reading the method names wrong (which is not surprising given how cryptic ruby method naming can be).
def current_user=(user)is actually read as defining the methodcurrent_user=that takes an argumentuser, whereasdef current_userdefines a methodcurrent_userthat takes no arguments. These are referred to respectively as setters and getters.Here’s a reference: Ruby (programming language): What are setters and getters in Ruby?
So that explains the duplication. On to your next question.
selfis a topic unto itself, worthy of its own discussion, so I won’t even try to explain it (here’s one reference out of many). For the purposes of this question it’s just important to remember that in order to set instance variables, you need to prefix your assignment withself, even within the class (where for other purposes it would be implicit). The rest of the line is a call to thecurrent_user=setter method I mentioned above, with the argumentuser.The reason it’s necessary is that you don’t want to be looking up the user from the token every time you need to get the current user. Take a look at the getter method:
What this says is: if I haven’t looked up and set the instance variable
@current_useryet, then look it up; if I have already set it, then just return it. That saves a lot of looking up.I think that answers your questions. There are a lot of deeper issues (
self, etc.) which you can find more information about elsewhere. Here’s one discussion of why you need to includeselfin setters on SO: Why do Ruby setters need "self." qualification within the class?UPDATE: Small clarification, that last link about using
selffor setters within the class is actually a bit off-topic, since you’re calling it within a module and not directly from a class. In the context of a module, theselfinself.current_user = userwill become the class that the module is included inside of, e.g.User.current_userif it was called within the classUser, etc. Again, another topic of discussion unto itself…