I’ll be honest, I had to go through this chapter twice just to get it. It’s a beast. And the concepts are much more complex than previous chapters. Part of the reason I’m posting notes throughout this tutorial is to ensure it sticks.
With that, I’m divvying this chapter into three sections:
- Creating the User Session (what happens when you enter stuff into a login form)
- Log in / Log out (what happens after successfully entering login info)
- Remember me [update: this post already pretty massive so I’ll cover this bit in Part 2]
Here we go…
1. Creating the User Session
Hartl begins with this context:
HTTP is a stateless protocol, treating each request as an independent transaction that is unable to use information from any previous requests. This means there is no way within the hypertext transfer protocol to remember a user’s identity from page to page; instead, web applications requiring user login must use a session, which is a semi-permanent connection between two computers (such as a client computer running a web browser and a server running Rails).
We attack this two difference ways. First by creating a user session (temporary / expire automatically), and then again later with a cookie (longer-lived).
First we create a sessions controller like so:
Initially I struggled with the concept of params[:whatever]
…but after some digging I found that it’s basically just a placeholder for a nested hash (user data submitted through the login form). So params[:session]
translates to { password: "foobar", email: "user@example.com" }
.
Going further, params[:session][:email]
just points to the submitted email address (and the same could be applied with ...[:password]
)1.
To pound this concept in a little further let’s explain what’s really going on with the punchline in the above code:
Here we need for the user to exist and for the password to be correct (kinda obvious when you think of what the login form does). So here are the possible results:
With an existing user
and the correct password via params[:session][:password]
both equating to true…the controller will then create the user session and send them on to the correct page.
The last part of this section applies a flash for incorrect logins (with accompanying test).
Here’s a quick look at the test (which FAILS):
We can then PASS our test (and apply the flash) by adding this line to the else
portion of the session controller code.
So far so good.
2. Log in / Log out
Kind of a big one. I’ll try to keep it brief — here’s what we’re doing:
- Log the user in with a temporary session cookie that expires automatically upon browser close
- define
log_in
method to add to thecreate
action (in session controller) - define
current_user
method to find the user in the database corresponding to the login session id - change the view (header links)for logged in users
- introduce fixtures + define
digest
method - ensure users are logged in automatically when they sign up
- define
log_out
method to add to thedestroy
action (in the controller) - test everything along the way
First we introduce the sessions helper to define the log_in
method, which looks like this:
We can then add that to our session empty controller comment from Section 1 above:
Next we need to define the current_user
to pull info from the database corresponding to their session id.
We use an instance variable (@current_user
) here in case it appears multiple multiple times on the page.
Also worth noting that the ||=
operation line is equivalent to the code below (but simpler/better):
So the ||=
operation will stop if @current_user
is available/true…and will otherwise continue on to the search.
Next we need to change the layout links for logged in users. We first do this by defining a method that checks if the user is logged in (in other words, is current_user
not nil
):
With that in place we’re able to add some conditional code to the header:
Almost there! Next we need to test everything with some sample user data. We do this with fixtures:
And then add an instance variable for :webb
in the login test:
I also mentioned that we need to log in new users automatically whenever they sign up. To do this just need to add log_in user
to the create
action in our user controller.
Then we add assert is_logged_in?
to the users_signup_test.rb
to ensure it works along the way.
Finally, we need the ability to log out. To do this we go back to our sessions_helper
to define the method:
Then we can use that method in our sessions controller:
The test for this is pretty gnarly but showcases a nice, full list of steps that are fairly easy to understand:
I’m guessing a lot of people bail on the project at some point during this chapter… For me, writing everything out here helped a HUGE amount, so on we go!
-
Stack Overflow provides a really helpful explanation of rails
params
as well. ↩