Prerequisite
- Rails 8 and Postgres should be installed on your system.
Introduction
-
Rails 8: The Ruby on Rails framework has continually been about conventions that make existence simpler. By combining the present authentication satisfactory practices (like has_secure_password or the integrated techniques) with some new Rails defaults, you can construct a secure, consumer-pleasant utility in no time.
-
Bootstrap: Bootstrap is a widely-used the front-stop framework that streamlines web layout with its series of equipped-made additives and grid layouts. It’s perfect for beginners and specialists alike, providing constant, mobile-pleasant styling out of the container. Bootstrap’s sturdy network guarantees ongoing support, everyday updates, and an abundance of beneficial, beneficial sources international.
Step 1: Create a New Rails 8 Project with Bootstrap
First things first—let’s generate a brand new Rails 8 application. Rails has made it super easy to include Tailwind CSS from the get-go:
rails _8.0.0_ new authentication_rails8 --css bootstrap --database=postgresql
This command will do a few neat tricks for you:
- Create a standard Rails folder structure
- Install Bootstrap CSS and set it up under the hood
Once the installation finishes, hop into your new application folder:
cd authentication_rails8
Step 2: Database Setup
Now, go ahead and configure your database. By default we used PostgreSQL in Step 1 or any other database you prefer.
We have to configure the config/database.yml
for database connection.
# If you're using the default database setup:
rake db:create db:migrate
This will create the development and test databases for you.
Step 3: Generate a User Model with Built-in Authentication
Rails provides the has_secure_password feature through ActiveModel, which gives us a straightforward way to implement password-based authentication. Let’s generate a simple User model:
rails g model User name:string email:string password_digest:string
It will generate models/user.rb, we have to add some validations and class methods to the model.
class User < ApplicationRecord
has_secure_password
# Simple validations
validates :email, presence: true, uniqueness: true
validates :password, presence: true, length: { minimum: 6 }, on: :create
end
Step 4: Create a Sessions Controller for Authentication Flow
Next, we’ll need a way for users to log in and log out. The common approach is to generate a Sessions controller (even though you can call it some thing makes sense for your app).
rails g controller Sessions new create destroy
Let’s break down these actions:
- New: Renders the login form
- Create: Authenticates the user (login)
- Destroy: Logs the user out
The Routes
Open your config/routes.rb
and set up some routes for sessions:
Rails.application.routes.draw do
get "up" => "rails/health#show", as: :rails_health_check
resources :users, only: [:new, :create]
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
delete 'logout', to: 'sessions#destroy'
root 'sessions#new'
end
The Sessions Controller
In app/controllers/sessions_controller.rb
, you might have:
class SessionsController < ApplicationController
def new
@current_user = User.find(session[:user_id])
end
def create
user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_path, notice: "Logged in successfully!"
else
flash.now[:alert] = "Invalid email or password"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_path, notice: "Logged out!"
end
end
Here, session[:user_id] = user.id
saves the user’s ID in the session, we are fetching user_id for new method, and getting the data from database.
Step 5: Create a Users Controller for Sign-up
We also need a Users controller to allow new sign-ups and handle user creation:
rails g controller Users new create
Inside app/controllers/users_controller.rb
, Code updates such as
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
session[:user_id] = @user.id
redirect_to root_path, notice: "Welcome aboard, #{@user.name}!"
else
render :new, alert: "Oops, something went wrong!"
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
Step 6: Change Views with bootstrap
Now for the fun part: using Boostrap CSS to style your forms and pages! Because we created our Rails project with --css=bootstrap, all the basic plumbing is already done for us.
Login Form
Let’s create a simple login form in app/views/sessions/new.html.erb
with Bootstrap classes:
<% unless @current_user %> <%= form_with(url: login_path, method: :post, local:
true) do |form| %>
<!-- Email input -->
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :email, class: "form-label text-start" %> <%= form.email_field
:email, class: "form-control" %>
</div>
<!-- Password input -->
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :password, class: "form-label" %> <%= form.password_field
:password, class: "form-control" %>
</div>
<!-- 2 column grid layout for inline styling -->
<div class="row mb-4">
<div class="col d-flex justify-content-center">
<!-- Checkbox -->
<div class="form-check">
<label class="form-check-label text-start" for="form2Example31">
Remember me
</label>
<input
class="form-check-input"
type="checkbox"
value=""
id="form2Example31"
checked
/>
</div>
</div>
</div>
<!-- Submit button -->
<%= form.submit "Sign in", class: "btn btn-primary btn-block mb-4" %>
<!-- Register buttons -->
<div class="text-center">
<p>Not a member? <%= link_to "Sign up", new_user_path %></p>
</div>
<% end %> <% else %>
<p>Hi <%= @current_user.name %></p>
<%= link_to "Logout", logout_path, method: :delete %> <% end %>
Now you have a clean, modern-looking login form with just a few Bootstrap utility classes.
Sign-up Form
For your sign-up page at app/views/users/new.html.erb
, you can do something similar:
<%= form_with(model: @user, local: true) do |form| %>
<!-- Email input -->
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :name, class: "form-label text-start" %> <%= form.text_field
:name, class: "form-control" %>
</div>
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :email, class: "form-label text-start" %> <%= form.email_field
:email, class: "form-control" %>
</div>
<!-- Password input -->
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :password, class: "form-label" %> <%= form.password_field
:password, class: "form-control" %>
</div>
<!-- Password confirmation input -->
<div data-mdb-input-init class="form-outline mb-4">
<%= form.label :password_confirmation, class: "form-label" %> <%=
form.password_field :password_confirmation, class: "form-control" %>
</div>
<!-- 2 column grid layout for inline styling -->
<div class="row mb-4">
<div class="col d-flex justify-content-center">
<!-- Checkbox -->
<div class="form-check">
<label class="form-check-label text-start" for="form2Example31">
Remember me
</label>
<input
class="form-check-input"
type="checkbox"
value=""
id="form2Example31"
checked
/>
</div>
</div>
</div>
<!-- Submit button -->
<%= form.submit "Create Account", class: "btn btn-primary btn-block mb-4" %>
<!-- Register buttons -->
<div class="text-center">
<p>Already a member <%= link_to "Sign in", login_path %></p>
</div>
<% end %>
Step 7: Let's check
Fire up your Rails server:
rails server
Visit localhost:3000. You’ll land on the login page, attemtp to sign up, then log in together with your credentials. If the entirety works, Great!
Layout and Flash Messages:
Use Rails’s flash messages to show success or error notifications. Bootstrap makes them look great with just a couple of classes:
<body>
<div class="layout">
<% if notice %>
<p class="bg-green-100 text-green-800 p-2 rounded mb-4"><%= notice %></p>
<% end %> <% if alert %>
<p class="bg-red-100 text-red-800 p-2 rounded mb-4"><%= alert %></p>
<% end %> <%= yield %>
</div>
</body>
Add style into application.css for layout design:
.layout {
width: 100%;
max-width: 330px;
padding: 15px;
margin: 0 auto;
text-align: center;
margin-top: 10em;
}