If you are a frequent user of Ruby on Rails, you know that building authentication and user management systems can be a time-consuming and complex process. That’s where Devise comes in — a powerful authentication solution that simplifies the process of implementing user management systems in your Rails applications. As a Rails developer who churns out apps regularly, I’ve found myself reaching for Devise every single time. However, with the release of Rails 7, I’ve had to adjust my workflow and make sure that Devise works seamlessly with the new version. In this blog post, I’ll share my workflow for setting up Devise on Rails 7 and walk you through the steps to get started with this essential tool. So, whether you’re a seasoned Rails developer or just getting started, read on for a comprehensive guide to setting up Devise on Rails 7.
Hang on, why should I use Devise?
Authenticating users in a web application is a critical task that requires careful consideration of security best
practices. Building authentication functionality from scratch can be a daunting and time-consuming process, particularly
for developers who are not well-versed in security principles. This is where Devise comes in handy. Devise provides a comprehensive and customizable solution that handles common authentication tasks such as user registration, login, and password resets, while also supporting various authentication mechanisms and providing robust security features. By using Devise, developers can save valuable time and ensure their application's authentication system is strong and reliable, allowing them to focus on building other aspects of their application. Let's see it in action on Rails 7.
Prerequisites
Before proceeding with the guide, ensure that you have a new or barebones Rails app created using rails new
.
Additionally, you should not have a User
model set up yet.
Step-by-Step Guide
-
Add Devise, Letter Opener, and Omniauth (optional) to your Gemfile:
... gem "devise", github : "heartcombo/devise", ref : "f8d1ea90bc3" gem "omniauth" ... group :development do ... gem "letter_opener" ... end
Note: cloning Devise from GitHub is necessary because it contains fixes for some Rails 7 incompatibilities.
-
Install the gems:
bundle install
-
Run the Devise install generator:
rails g devise:install
This generates the devise.rb
initializer and adds the en
locale at config/locales/devise.en.yml
.
-
Add the following Devise-specific configurations to
config/development.rb
:
# For Devise config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } # For Letter Opener config.action_mailer.delivery_method = :letter_opener config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true
-
Generate the
User
model with Devise:
rails g devise user
This creates the user model files as well as a preliminary migration.
-
Edit the migration to add the fields you need:
## Identifying fields t.string :first_name, null : false, default : "" t.string :last_name, null: false, default: ""
Also, uncomment the trackable
, confirmable
, and lockable
fields (and accompanying indexes).
- Edit
user.rb
and addconfirmable
,trackable
,lockable
, andomniauthable
to Devise. -
Tweak options in
config/devise.rb
to suit your needs. For example, you may want to increase theremember_for
option to a couple of months:
config.remember_for = 2.months
In the same file, change the default email to one from your application:
```ruby
config.mailer_sender = 'no-reply@designerdiscount.club'
```
-
Generate the Devise views so you can modify them later:
rails g devise:views
Migrate the database:
rake db:migrate
- Add the following code to
application.html.erb
right above theyield
block:
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
Try it out! Start your rails server and head to http://localhost:3000/users/sign_up and create a new user. You should receive an email which opens in the browser (via letter_opener). Great, it’s working!
Deny logged-out access to a controller action and test it out. Create a
home
action in an existing controller,
which isPagesController
in this example:
class PagesController < ApplicationController
def landing; end
def home; end
end
Let’s redirect the user to the landing page if they try to access home
but are logged out.
def landing
redirect_to(action: :home,
params: request.query_parameters) if user_signed_in?
end
def home
redirect_to(action: :landing,
params: request.query_parameters) unless user_signed_in?
end
-
Edit the global header to hide the sign-in link if the user is signed in:
<% if user_signed_in? %> <li class="flex"> <%= link_to 'Logout', destroy_user_session_path, method: :delete, data: { turbo_method: :delete } %> </li> <% else %> <li class="flex"> <%= link_to "Sign up", new_user_registration_path, rel: 'noopener noreferrer' %> <%= link_to "Login", new_user_session_path, rel: 'noopener noreferrer' %> </li> <% end %>
That’s it! You now have a basic setup for user authentication using Devise on Rails 7. You can customize the generated Devise views with Tailwind or Bootstrap to match your app’s design. Want to learn more? Check out the Devise wiki. Preparing for a coding interview? Check out Firecode.io.
Oldest comments (1)
Small nitpick but there's a formatting error in that section where you describe what to put in the Gemfile. This line:
has spaces before each colon which break it when you try to run it. It's a simple fix , but for newer devs, they may get confused on why copy / paste of those commands will not work in the Gemfile.
Great article ! Glad to see that they finally ironed out the issues with Devise and Rails 7 becuase this had been a blocker for me using Devise much earlier this year, and I didn't feel like jumping through all of the workaround hoops in the web. Thank you.