Rails 8 comes with a built-in authentication generator. However, it doesn’t yet come with registrations. Here’s how to add them.
Rails auth generator
To generate authentication scaffold, run:
$ rails generate authentication
This will create User
and Session
models as well as sign-in forms. But there is little to do without registrations.
Registrations
To add registrations, we’ll add a new RegistrationsController
, route, and view.
The registration controller can look like this:
# app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
# Include Authentication module unless it's already in ApplicationController
include Authentication
allow_unauthenticated_access
rate_limit to: 10,
within: 3.minutes,
only: :create,
with: -> { redirect_to new_registration_url, alert: "Try again later." }
def new
@user = User.new
end
def create
@user = User.new(safe_params)
if @user.save
start_new_session_for @user
redirect_to after_authentication_url, notice: "Welcome!"
else
flash[:alert] = "Email or password confirmation invalid."
render :new, status: :unprocessable_entity
end
end
private
def safe_params
params.require(:user).permit(:email_address, :password, :password_confirmation)
end
end
The code is surprisingly simple. We rely on the generator’s Authentication
module and start_new_session_for
method to sign people in. And we rely on has_secure_password
to do the right thing when providing users with password
and password_confirmation
.
Note that it doesn’t come with any constrains for passwords or email address, but we can add them:
# app/models/user.rb
class User
validates :email_address, presence: true
validates :password, length: { minimum: 10 }, if: -> { new_record? || changes[:password_digest] }
validates :password, confirmation: true, if: -> { new_record? || changes[:password_digest] }
validates :password_confirmation, presence: true, if: -> { new_record? || changes[:password_digest] }
end
Then let’s add the view:
<!-- app/views/registrations/new.html.erb -->
<%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
<%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
<%= form_for @user, url: registrations_path do |form| %>
<%= form.label :email_address, "Email:" %>
<%= form.email_field :email_address, autofocus: true %>
<%= form.label :email, "Password:" %>
<%= form.password_field :password, required: true %>
<%= form.label :email, "Confirmation:" %>
<%= form.password_field :password_confirmation, required: true %>
<%= form.submit "Register" %>
<% end %>
Finally, let’s add the route:
Rails.application.routes.draw do
resource :session
resources :passwords, param: :token
# add this
resources :registrations, except: [:index, :show, :destroy]
end
And that’s it! You can now register as a new user.
Get Test Driving Rails and make your tests faster and easier to maintain.