RoR User Auth

Devise is the most widely used authentication gem for Rails. It handles user registration, login, logout, password reset, and email confirmation out of the box. Instead of writing authentication from scratch — which is complex and error-prone — you install Devise and get a secure, battle-tested system in minutes.

Install Devise

Add Devise to your Gemfile:

gem "devise"

Run the installer:

bundle install
rails generate devise:install

The installer prints a few instructions. Follow them:

1. Add this to config/environments/development.rb:
   config.action_mailer.default_url_options = { host: "localhost", port: 3000 }

2. Make sure you have a root route in config/routes.rb:
   root "pages#home"

3. Add flash messages to app/views/layouts/application.html.erb:
   <%= notice %>
   <%= alert %>

Generate the User Model

rails generate devise User
rails db:migrate

This creates a fully configured User model and migration with columns for email, encrypted password, reset password tokens, and remember-me tokens.

What Devise Generates Automatically

Routes added to config/routes.rb:
  devise_for :users

This creates all these URLs:
  GET  /users/sign_in       ← login form
  POST /users/sign_in       ← submit login
  DELETE /users/sign_out    ← logout
  GET  /users/sign_up       ← registration form
  POST /users/registration  ← submit registration
  GET  /users/password/new  ← forgot password form
  POST /users/password      ← send reset email
  GET  /users/password/edit ← reset password form

Protecting Pages with Authentication

Add before_action :authenticate_user! to any controller to require login:

class ArticlesController < ApplicationController
  before_action :authenticate_user!, except: [:index, :show]

  # index and show are public — no login needed
  def index
    @articles = Article.all
  end

  def show
    @article = Article.find(params[:id])
  end

  # new, create, edit, update, destroy require login
  def new
    @article = Article.new
  end
end

Devise Helper Methods

Devise provides helpers available in controllers and views:

current_user          → the logged-in User object (nil if not logged in)
user_signed_in?       → true if someone is logged in
user_signed_out?      → true if no one is logged in
authenticate_user!    → redirects to login if not signed in
sign_in(@user)        → programmatically log in a user
sign_out(current_user)→ programmatically log out

Use them in views:

<% if user_signed_in? %>
  <p>Welcome, <%= current_user.email %></p>
  <%= link_to "Log Out", destroy_user_session_path, method: :delete %>
<% else %>
  <%= link_to "Sign In", new_user_session_path %>
  <%= link_to "Sign Up", new_user_registration_path %>
<% end %>

Add Extra Fields to the User Model

Devise manages email and password. For extra fields like name, generate a migration:

rails generate migration AddNameToUsers name:string
rails db:migrate

Then permit the extra field in your ApplicationController:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
  end
end

Customizing Devise Views

Devise uses its own built-in views by default. Generate them to customize the HTML:

rails generate devise:views

This creates editable view files in app/views/devise/:

app/views/devise/
  sessions/
    new.html.erb          ← login form
  registrations/
    new.html.erb          ← sign up form
    edit.html.erb         ← edit profile form
  passwords/
    new.html.erb          ← forgot password form
    edit.html.erb         ← reset password form
  confirmations/
    new.html.erb          ← resend confirmation email

Devise Authentication Flow

User visits /posts/new (protected by authenticate_user!)
        |
        v
Devise checks: is current_user present?
        |
        +-- Yes → Continue to posts#new
        |
        +-- No → Redirect to /users/sign_in

User fills in email and password, submits
        |
        v
Devise looks up User by email
Devise compares password with stored hash using bcrypt
        |
        +-- Match → Create session, set current_user, redirect back to /posts/new
        |
        +-- No match → Show "Invalid email or password"

Devise Modules

Devise is modular. Enable only what you need in your User model:

class User < ApplicationRecord
  devise :database_authenticatable,   ← email/password auth
         :registerable,               ← sign up
         :recoverable,                ← password reset
         :rememberable,               ← "Remember me" checkbox
         :validatable,                ← email and password validations
         :confirmable,                ← email confirmation
         :lockable,                   ← lock account after failed logins
         :trackable                   ← track sign-in count and IP
end

Start with the first five modules for most apps. Add :confirmable when you need verified email addresses.

Connecting Posts to the Logged-In User

def create
  @article = current_user.articles.build(article_params)
  if @article.save
    redirect_to @article, notice: "Article published."
  else
    render :new, status: :unprocessable_entity
  end
end

Using current_user.articles.build automatically sets the user_id on the new article to the logged-in user's ID. No manual assignment needed.

Devise handles the hardest parts of authentication correctly — password hashing, session management, and secure token generation. Use it instead of building authentication manually.

Leave a Comment

Your email address will not be published. Required fields are marked *