Heads up! To view this whole video, sign in with your Courses Plus account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Design and Development!
You have completed Design and Development!
Preview
In this video, we setup the user session, which is the model that handles logging in and out. Download the Beginning of the Project or the Completed Project
This video doesn't have any notes.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
[Master Class] [Designer and Developer Workflow] [Creating the User Session]
0:00
So now, we've updated our form view where we can have our password
0:05
and password confirmation and our properly crypted password
0:09
will be stored in the database.
0:12
So, we can pretty much register and edit all the users.
0:14
So, the next step is to actually log in.
0:18
In order to log in, we'll be using a session, and a session is
0:21
a model that sort of handles a particular session.
0:25
So, when we log in, we'll be creating a new session for a user,
0:28
and when we log out, we'll be deleting a session.
0:32
So, it works just like our other models where we'll be creating and deleting things.
0:34
So, let's go ahead and generate our session.
0:39
So, we saw before that there is a generator that's installed with authlogic
0:42
called "authlogic session," and basically, we can use this to generate our user session
0:47
which is a session that authenticates a user.
0:53
So, we'll do "rails generate authlogic:session"
0:57
and we'll call this a "UserSession."
1:07
So, now it's gone ahead and created a file called "app/models/user_session.rb,"
1:13
so let's go check that out, and here we are in app/models/user_session.rb.
1:18
Now, you'll notice this is a little bit different than our typical model.
1:25
It doesn't inherit from ActiveRecord base.
1:28
In fact, there is no database table for the user session.
1:32
The model itself is represented in the database,
1:35
so it can abstract away the actual logging in and logging out.
1:38
So instead, it inherits from Authlogic Session Base,
1:42
and that class provides us with a lot of functionality,
1:47
which will ultimately allow us to log in.
1:50
Now, since it's called a user session, it's assuming that
1:53
what it's going to be authenticating against is a user class,
1:56
which will act as authentic, which we've already gone ahead and set up.
2:00
So, those assumptions should be true.
2:05
So now, the steps are we're going to create a new controller for handling our authentication,
2:08
or handling our actual user sessions, and when we want to log in
2:13
we'll call the create method, and we'll generate a new user session
2:18
based on the authentication credentials that have been passed.
2:22
And if that's successful, then we'll have a new session where somebody is logged in,
2:26
and if it's not successful, it will redirect them back to the new user session screen
2:31
or the log in screen.
2:35
So, let's go ahead and generate a new controller for our user sessions.
2:37
So, we'll do "rails generate controller" and we'll call this "UserSessions,"
2:41
and what I'm going to do is define a method called "new" which will be our log in,
2:52
and this will just generate a view for the new field, which is really the only
2:58
user visible action that the user sessions will implement.
3:02
So, if we run that, it's created a new controller called "user sessions controller,"
3:06
and it's created a new view file under views/user_sessions/new.html.haml,
3:10
and that new .html file will be our log in page.
3:17
We'll go ahead and adjust our routes later so the route will look like /login.
3:21
So, let's go to our new user sessions controller because
3:27
it's just generated an empty controller.
3:30
What we have to do is now add the logic that we want to add to it.
3:32
So, let's go ahead, open up controllers, user session controller.
3:37
So, here it's generated a new method stub, and this is what's going to be called
3:42
when we go to usersessions/new, and what we need to do is
3:47
instantiate a new user session, and this will be useful because in our form
3:52
our user session instance is actually what we're going to be basing our form off of.
3:58
So, since we have a real object of the user session,
4:03
it allows us to treat it just like any other model in our application.
4:06
So, we'll just go ahead and say "@user_session = UserSession.new."
4:10
Then our new .html view will render and display an empty form for user session.
4:20
So, when that form submits or they hit log in and it submits,
4:28
that's going to go to create.
4:32
And this is the method where we're actually going to do our authentication.
4:35
So, in this create method is actually where we're going to do our authentication.
4:39
So, the first step is to get a user session instance.
4:43
This will be a lot like our new method.
4:46
We'll do "UserSession.new."
4:48
However, this time we've been passed in parameters, so we want to instantiate
4:52
our user session with the, let's say, email and password that were submitted.
4:56
So, to do that we'll just pass in (params[user_session]).
5:01
Now, this just looks like any other create method where we instantiate a new object
5:09
based on the parameters, and that's what's really great about authlogic
5:13
is it really has the same sort of pattern as any other model.
5:16
So, the next step is where the real magic happens.
5:21
We're going to try to save this user session.
5:24
So, we'll say "if @user_session.save,"
5:26
and then there's going to be an else and end here.
5:33
So, when we try to save a user session, what authlogic does is it takes the information
5:37
that it was passed, basically our email and password, and it tried to find a user
5:42
who matches those credentials.
5:47
If it finds one and we save it, it will go ahead and say that we are authenticated
5:50
and return true, and it will set the cookie saying this person is logged in
5:55
so we can handle our true session here, so at this point they are logged in.
6:00
So, why don't we go ahead and just leave a flash here,
6:05
and this is just a notice at the top of the page,
6:09
so we'll say "flash(notice) = "Welcome to EasyJobs"
6:11
or something along those lines.
6:19
We can go ahead and change this easily later.
6:21
So, if we're logged in, we want to go ahead and redirect them somewhere.
6:23
So, we'll just say "redirect_to jobs_url."
6:25
Now, in this else clause here, we were not able to save our user session,
6:33
which means that based on the information that was passed in via params,
6:36
which I just realized I misspelled.
6:41
It is not "parms."
6:43
There we go.
6:45
Based on that information, we are not able to log in, so what we want to do is actually
6:47
go ahead and just render our new form again.
6:51
So, we'll say "render action of new" and what this does is
6:54
since we have our @user_session set with the information that was submitted
7:01
when we render this new action here, it will actually prepopulate the email field
7:06
with what they pass through.
7:12
The actual password field should be blank because we don't want to pass
7:14
the password back to them, but it's a nice little tip that we will be able to give
7:17
to the user that you don't have to enter your email again, or you can review it.
7:21
So, this handles our logging in.
7:25
Basically, with the user session we just pass it some information like email and password.
7:27
If it saves, they're logged in.
7:31
If not, they need to try again, and destroying is pretty much the same thing.
7:34
When we log out, we want to go ahead and destroy this user session.
7:40
So, we'll define destroy.
7:47
So, how do we find our current user session?
7:50
Well, this is code that we're going to need throughout the entire application.
7:54
We're going to need to be able to search for the current user session
7:57
and the current user in order to, for instance, display who's logged in,
8:00
to perform authorization checks to see if they're allowed to perform certain actions.
8:06
So, what we're going to do is write different methods, and we'll save them
8:10
in our application controller so they're available to us at any place in our application.
8:13
So, we're going to take a break from writing our user sessions controller
8:17
to go to our application controller, and our application controller
8:21
is in app, controllers, application controller.
8:25
So here, we're going to define two private methods.
8:30
So, we'll define private and down here is where we'll define our method.
8:33
The first method we want to do is current user session, "current_user_session."
8:38
And we'll define another method which will be current user,
8:46
and where current session will actually retrieve the current user session
8:52
more often we actually want the user that's associated with the session,
8:56
so this convenience method "current_user" will provide that.
9:00
Now, the way we can get the current user session is by using the user session
9:04
class method called "find," and authlogic will use its ways to find out
9:08
if there is a current user session and return that instance to you if it exists, otherwise no.
9:13
Now, while this will technically work, we may be calling current user session
9:18
multiple times in our request.
9:23
So, what we want to do is make sure we're not calling user.find all the time.
9:26
Instead, we want to cache or memoize the result into an instance variable
9:29
so we're not calling user.find over and over again.
9:34
So, the first thing we'll do is we'll say "@current_user_session = UserSession.find."
9:37
So, after the first time we've called it, @current_user_session is defined.
9:47
So, if we call it a second time, what we want to do is check if @current_user_session
9:51
has been defined and if so, we want to return that since we already did the find call on it.
9:55
We can just return the cached result, otherwise we'll actually want to do
10:01
the User.Session find here.
10:06
So, what we'll do is we'll say "return @current_user_session"
10:09
if we have current user session defined, so we'll do "defined?(@current_user_session).
10:16
Another reason we can't just say "return @current_user_session
10:26
if @current_user_session" is because if they are logged out,
10:29
current_user_session will be nil and it will try to reevaluate User.Session.find every time
10:33
if somebody's logged out.
10:40
So, this is just a way of us caching so don't have to call User.Session.find
10:42
over and over again if we call current user session over and over again.
10:45
Now, let's say we want to get the current user.
10:49
Well, to do that we will need to get the current user session,
10:51
so we can just type in "current_user_session" and call that method,
10:54
and we can call ".user" on it.
10:59
Now remember, if somebody's logged out, current user session will be null
11:02
and if we try to call user on that, well, we're going to get an error.
11:05
So, what we need to do is check if current user session is true
11:09
or a truthy value or just not nil.
11:14
So, by using this here, we'll say "current_user_session," make sure it's true.
11:17
If it is, then we'll call "current_user_session.user."
11:21
Now, if current user session is false or they're logged out,
11:24
when this evaluates to nil, or false rather, it will not evaluate this side
11:27
so we won't get an error.
11:32
Now you can see that we've called current user session twice in quick succession,
11:35
which is why this caching is important.
11:38
Again, we don't want to continue doing this over and over again,
11:41
so let's implement the same sort of caching, so let's implement
11:43
the same sort of value caching here that we did here.
11:46
So, instead of just returning, we'll return it while setting it to current user,
11:49
and then before we try to do that, we'll say
11:57
"return @current_user if defined?(@current_user)."
11:59
So now, from anywhere in our controller we could type in "current user,"
12:08
and if somebody's logged in, we'll get a user instance of the person who's logged in,
12:11
and if they're not logged in, then we'll get nil.
12:15
We could do the same thing for current user session if we actually wanted
12:18
to get the session which we actually do in our log out method.
12:21
Now, before I switch away from this, there is one last thing I want to do.
12:25
So, we'll call helper method and pass it the symbol "current_user_session"
12:33
and "current_user."
12:39
What this does is it makes the methods current user session and current user
12:43
available in our views as helper methods because quite often in our views
12:46
we're going to want to access current user.
12:51
So now, we can go ahead and save that out.
12:53
So, let's just hop back to our user sessions controller
12:56
to see if we can't implement destroy now.
12:59
Well, now, this is as simple as doing "current_user_session.destroy."
13:01
Now, you'll realize that if somebody's logged out already then current user session
13:11
will return null and trying to call destroy on it will cause an error.
13:15
Now, there's a couple of different ways we could solve this.
13:20
The most correct, in my opinion, way to do this would be to restrict the destroy method
13:22
so it's only visible to people who are logged in, and that will happen
13:28
when we start doing our authorization.
13:32
Right now what I want to do is just to make sure we don't get this error,
13:35
I'm going to call "current_user_session && current_user_session.destroy."
13:38
That way, if there is no current user session, the destroy method will not be called.
13:46
No harm, no foul.
13:51
It will be a little bit weird to log out while you're logged out, but right now it avoids the error.
13:53
So, then I'm just going to go ahead and just type in "flash[:notice]"
13:59
and just say "You are now logged out."
14:04
And let's go ahead and just redirect to the jobs url again, the home page.
14:11
So, now we've got the controllers and models for our session set up.
14:18
We have a user session which handles all of the logic of logging in
14:21
and authenticating the user.
14:25
We have the user sessions controller which will ultimately
14:27
be our log in and log out controller.
14:30
We still need to create the views for it, and in our application controller
14:32
we've created a couple of methods that will allow us to get the current session
14:36
and the current user.
14:39
So, up next we're going to go ahead and jump towards the front end
14:41
and create our log in form and some information that will be displayed
14:44
when you're logged in or when you're logged out.
14:48
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up