I was really disappointed with the has_secure_password section because I didn’t feel prepared for all the concepts introduced in the lab. So here’s a blog post about some of the steps I took to navigate these concepts.
What the heck? SessionsController? How does this interact with UsersController?
-
Get some more background knowledge. I checked out this wordy (but helpful) guide in seciton 8.1.1 to learn more about what SessionsController was intended for. I also read around some other sections on the page as a refresher on sessions and routes.
-
I learned that SessionsController really should be the controller that manages
sessions#new
(login page),sessions#create
(setting your session_id), andsessions#destroy
(the logout feature) -
What does this leave UsersController for, then?
users#new
should be a sign-up page.users#create
should create a new user if the passwords match.
Preparing to use has_secure_password
-
Add the
bcrypt
gem to your Gemfile -
Run
bundle install
& update -
Create your users table (remember NOT to make a password column - this isn’t secure. Make a
password_digest
column so that bcrypt can save only the salted and hashed password digest) -
Run your migrations
-
Create your user model & play around with it in console to make sure it’s working as expected
-
Add
has_secure_password
to your user model
Woop woop - now you have access to methods like password & password_confirmation
to verify your password!! You also have access to things like authenticate to make sure that the user’s submitted password matches the expected password.
How do I make new users? (This should be a lot of review!)
- Set up my UsersController
class UsersController < ApplicationController def new end def create end end
- Set up my user routes for submitting and creating a user in the database
- get ‘/users/new’, to: “users#new”
- post ‘/users’, to: “users#create”
- I made the user/new view with a nice create a user form
<%= form_for :user, url: ‘/users' do |f| %> Username: <%= f.text_field :name %> Password: <%= f.password_field :password %> Password Confirmation: <%= f.password_field :password_confirmation %> <%= f.submit "Submit" %> <% end %>
-
Now, my tests can go to create a new user. The data is getting pushed into the UsersController
users#create
action. So it was time to set up my create action. I wanted to make sure I saved a user to the database, and that it redirected me to try again if it didn’t work. If it did work, I wanted the user to be logged in.@user = User.new(user_params) if !@user.save redirect_to '/users/new' else session[:user_id] = @user.id redirect_to "/" end
NOTE: I also added strong params to the bottom of this section:
params.require(:user).permit(:name, :password, :password_confirmation)
…. isn’t that cool how the password_confirmation is a nice given method with you when you do has_secure_password 🙂
I’m in!! Yes!!! But next time I visit this page… I’m gonna need to login & logout. I’m going to need a sessions controller.
How do I set up my SessionsController for submitting, creating, and destroying a session in the browser?
- Set up your sessions controller routes.
class SessionsController < ApplicationController def new end def create end def destroy end end
- I used that guide to set up my routes
get '/login', to: 'sessions#new' (or to make it restful, make it /sessions/new) post '/login', to: 'sessions#create' (or just /sessions) delete '/logout', to: 'sessions#destroy' (or just /sessions)
- I made the
session/new view
& I copied the same create user form into thesession/new view
<%= form_for :user, url: ‘/login' do |f| %> Username: <%= f.text_field :name %> Password: <%= f.password_field :password %> Password Confirmation: <%= f.password_field :password_confirmation %> <%= f.submit "Submit" %> <% end %>
-
Now, when the tests ran, there was a
sessions#new form
to view. That form would post tosessions#create
. Sessions create now could use the data. So I set up the create action. (I have to admit… I had to look at the solution at this part. I was starting to lose my mind. I’m going to leave something out that’s too solution-specific.) - Then you would to check and see if the user was authenticated or not.
- The first step is to find the user so you can later compare credentials - use a
User.find_by
- Then you need to actually try to authenticate them (a fun note on try!! -
user = user.try(:authenticate, params[:user][:password])
- The first step is to find the user so you can later compare credentials - use a
- You will need to redirect_to the
users#new
action (to make a new user) or the login page (try again) if not.- If they were authenticated, try to set
session[:user_id]
to the user’s id. Redirect them to your homepage or wherever!
- If they were authenticated, try to set
- To let the user logout, go into
sessions#destroy
to use the .delete method on thesession[:user_id],
and redirect them to your homepage
Fixing this implementation of my SessionsController made all of my tests turn green. Cross checking the solution, this seems to be mostly accurate. This may not be 100% accurate, but doing all of this really helped me to start building a conceptual foundation!