User Authentication from Scratch

Well, hello there <username>!

Today we are going to start a Rails User Authentication from scratch. This will go step-by-step through everything you need to create basic user registration and login. Basic, people, basic. You can make it pretty later.

Personally, I haven’t really made great friends with RSpec 3. I am looking forward to that in the future.

$ bundle install
$ rails g rspec:install

Open up spec_helper, delete all those comments, and add the following below the other require:

require 'capybara/rspec'

Time to make our first commit! Feel free to git add . here (and only here), there is a lot of new files that Rails just made for ya. Check it out in the browser if you want, but it might bore you to tears. Open up a new terminal window, navigate to our little directoy here, and $ rails s. Then go back to your command line terminal window.

Time to get crackin! I’m just going to have you dump all the tests in at once, and you can remove the pending after each commit. Below is your test, put it in a new folder called features in a file user_auth_spec.rb:

Looks like we need to “root” our app. Open /config/routes.rb and delete all the comments. This should be your only route:

root 'welcome#index'

Run RSpec again. Just keep running it after every addition to see what is next.

$ rspec

Now we make add the WelcomeController. Add welcome_controller.rb to /app/controllers/ with the following:

class WelcomeController < ApplicationController
def index
end
end

Running RSpec again tells us we need a view. Add index.html.erb to the new file folder /app/views/welcome/. Run RSpec again, and looks like we need to add a link. We are going to use some rails helpers, so before we actually add that link, add the following routes to our routes.rb file:

resources :users

Are you curious what you really just did?

$ rake routes

Whoa. That’s a lot of routes right there. Moving on… back to our welcome/index.html.erb:

<%= link_to 'Sign up', new_user_path %>

Now we need a users_controller.rb in the same directory as our welcome_controller.rb. Add the following:

class UsersController < ApplicationController
def new
end
end

And now a view… add new.html.erb into a new file folder /app/views/users/. Run RSpec again, and looks like we need to add a form for our new user to fill out. We are going to use some rails helpers again, and this is what it looks like:

We can’t pass in nil? What does that even mean? Well, that @user isn’t getting passed in from our controller… eventually we want that to be a User object. But for that we need a migration. Go to the terminal, and…

$ rake g migration CreateUsers email:string password_digest:string

Feel free to check out that migration file in the db folder. We will also need to add a model user.rb in the /app/models/ folder. You can delete that .keep file after you add the model file, it’s just holding that directory for you when there are no files within it. Within that model file, we will add the following:

Now we eventually want to redirect to our root path. But first, we have to get that logged in thing working for real, not just that User.last cheater. We want to add “sessions” to our little app. In our application_controller.rb, we will add the following method:

Nice! We are well on our way! Let’s remove another pending and see what RSpec and our test have in store. Looks like we need a new link to “Log in”. Add this above the “Sign up” link in our /app/views/welcome/index.html.erb file:

<%= link_to 'Log in', new_login_path %>

Next we add the method new to our LoginController. This will create a “new” logged in session. Next we need to add the view. We are going to pass in a new user to the view, so go ahead and add that to our method new in the LoginController:

def new
@user = User.new
end

Now we will add the login form to the view page (new folder and file) /app/views/login/new.html.erb:

That first line is a little weird… we are creating a view for @user but we want it to post to /login not /user, so we need to add that hash in there. Now we need to have a create method in our LoginController:

Let’s un-pend the next test! What does RSpec say? Whoa, what happened? It’s like the login create method just totally broke. Check that LoginControllercreate method out… oh! We have a “happy path” but what happens if the person trying to log in enters the wrong information? We will change that method to look like this:

Only one more test to go… let’s un-pend! Oh, wow, looks like our previous changes took care of this scenario too… a user cannot login with the incorrect password. Let’s amend that commit and commit this and the last together. Check it out in the browser to make sure all is good.