DEV Community

Brittany
Brittany

Posted on

Day 54 : #100DaysofCode -Review on setting up log in & sign up

As promised, I am going to review how I added user authentication functionality onto my simple todo application and hopefully tomorrow I will be able to share how I added user authorization.

1. Create Branch

First you should create a new branch, just to be safe!

git checkout -b user_setup

2. Generate User Resource

Run the following code:

rails g resource User name username password_digest

which will generate a User MVC.

3. Add Unique User Id to Lists

rails generate migration AddUserToLists user_id:integer

which will add a user_id to be referenced in the List we created in my prior post.

Check out the schema, it should look similar to this:

ActiveRecord::Schema.define(version: 2020_07_24_000911) do create_table "items", force: :cascade do |t| t.string "description" t.integer "list_id" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.integer "status", default: 0 end create_table "lists", force: :cascade do |t| t.string "name" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.integer "user_id" end create_table "users", force: :cascade do |t| t.string "name" t.string "username" t.string "password_digest" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end 
Enter fullscreen mode Exit fullscreen mode

Make sure to migrate your table!

4. Gemfile

Next, make sure to go to your gemfile and add/uncomment the bycrypt gem.

5. Models

Next we want to set up our models.

Your user model should have many lists and have a secure password:

class User < ApplicationRecord has_secure_password has_many :lists end 
Enter fullscreen mode Exit fullscreen mode

Your list model should belong_to user:

class List < ApplicationRecord belongs_to :user has_many :items end 
Enter fullscreen mode Exit fullscreen mode

6. Check it all out in rails console

m = User.new(name: "Sincerely", username: "brittany", password: "password") m.save 
Enter fullscreen mode Exit fullscreen mode

Should return true

Add some validations in your model

class User < ApplicationRecord has_secure_password validates :username, uniqueness: true has_many :lists end 
Enter fullscreen mode Exit fullscreen mode
class List < ApplicationRecord belongs_to :user has_many :items validates :name, presence: true end 
Enter fullscreen mode Exit fullscreen mode

Check it out in rails console

n = User.new(name: "steve", username: "brittany", password: "password") n.save 
Enter fullscreen mode Exit fullscreen mode

should return false (because of validations)

If you run the following:

n.errors 
Enter fullscreen mode Exit fullscreen mode

it should return => username already taken confirming our validations are up and working.

Let's update the username of n so that it will save.

n.username = "steve" n.save 
Enter fullscreen mode Exit fullscreen mode

Now that should return true

We've created some list in the past, lets see what we've made:

List.all

a = List.first
a.user_id = n.id - sets the List_id to user 1 id.
a.save

b = List.find(2).user_id = m.id
b.save - sets the List_id to user 2 id.

P.S. - If you have no list create a list and add a user:
p = List.create(name: "this is a list")
p.user_id = n.id
p.save

NEXT: M-V-C Let's create the sign up

7. Create new route in config/routes.rb:

get "/signup" => "users#new", as: "signup" 
Enter fullscreen mode Exit fullscreen mode

So now your routes should look something like this:

 resources :users, except: [:new] get 'items/create' resources :lists do resources :items end get "/signup" => "users#new", as: "signup" root 'lists#index' 
Enter fullscreen mode Exit fullscreen mode

8. Create new user instance in controller

class UsersController < ApplicationController def new @user = User.new end end 
Enter fullscreen mode Exit fullscreen mode

9. Set up your signup view page:

<%= form_with model: @user, local: true do |f| %> <%= f.text_field :name, placeholder: "name" %> <%= f.text_field :name, placeholder: "username" %> <%= f.password_field :name, placeholder: "password" %> <%= f.submit %> <% end %> 
Enter fullscreen mode Exit fullscreen mode

10. Now update your create method in user

 def create @user = User.new(user_params) if @user.save session[:user_id] = @user.id #logs in the user -- tells app that user is logged in redirect_to lists_path else render :new end end 
Enter fullscreen mode Exit fullscreen mode

11. Lets work on our application view

 <header> <%= navbar %> </header> 
Enter fullscreen mode Exit fullscreen mode

Lets create a create a helper named navbar


 def navbar if logged_in? render "layouts/logged_in_navbar" else render "layouts/logged_out_navbar" end end 
Enter fullscreen mode Exit fullscreen mode

12. Now, we have to create the helper methods, logged_in and current user in the application controller:


 helper_method :logged_in? helper_method :current_user private def logged_in? !!current_user end def current_user User.find_by(id: session[:user_id]) end 
Enter fullscreen mode Exit fullscreen mode

13. Create the two layout partials mentioned in your navbar helper

logged_in partial

 <%= button_to 'Log Out', '/logout', method: :delete %> 
Enter fullscreen mode Exit fullscreen mode

logged_out partial

 <%= link_to 'Log In', login_path %> <%= link_to 'Sign Up', signup_path %> 
Enter fullscreen mode Exit fullscreen mode

14. Update the routes


 Rails.application.routes.draw do root 'lists#index' resources :users, except: [:new] get "/signup" => "users#new", as: "signup" get "/login" => "sessions#new", as: "login" post "/login" => "sessions#create" delete "/logout" => "sessions#destroy" get 'items/create' resources :lists do resources :items end end 
Enter fullscreen mode Exit fullscreen mode

15. Create a sessions controller

rails g controller sessions

16. Create a sessions/new view

<%= form_tag("/login") do %> <%= text_field_tag :username,nil, placeholder: 'username'%> <%= password_field_tag :password, nil, placeholder: 'password' %> <%= submit_tag "Login"%> <% end %> 
Enter fullscreen mode Exit fullscreen mode

Update your sessions controller to have flash messages!

 def create @user = User.find_by(username: params[:username]) if @user && @user.authenticate(params[:password]) # session[:user_id] log_in(@user) flash[:sucess] = "Welcome, #{@user.username}" redirect_to lists_path else flash[:danger] = "Improper credentials given" redirect_to login_path end end 
Enter fullscreen mode Exit fullscreen mode

17. Update your application_controller

 def log_in(user) session[:user_id] = user.id end def authenticate redirect_to login_path if !logged_in? end 
Enter fullscreen mode Exit fullscreen mode

18. Update your application.html.erb to show the flash messages


 <header> <% flash.each do |k,v| %> <%= v %> <% end %> <%= navbar %> </header> <%= yield %> 
Enter fullscreen mode Exit fullscreen mode

And you have now implemented user authorization on your application.

Thanks for reading!

Sincerely,
Brittany

Top comments (0)