Skip to content
Menu
Railshero
  • Blog
  • About Me
  • Contact Me
  • Privacy Policy
Railshero
Devise tutorial adding avatars with active storage

Devise tutorial: adding avatars with active storage

Posted on October 21, 2021October 21, 2021 by Rails Hero

User Avatars

Everybody knows what user avatars are. But if you’ve been living under a rock; ‘user avatars’ or ‘Profile Pictures’ are graphical illustrations of a user’s persona or character; i.e they represent/describe the user’s personality or alter ego. The word ‘avatar’ comes from the sanskrit language meaning ‘a manifestation of a deity or released soul in bodily form on earth‘. A popular example of an avatar would be a selfie uploaded to an instagram profile DP. Avatars can either be a 2D image/video/animation or even in 3D forms (eg; Xbox Live Avatars). Earlier, avatars have been very popular on forum based applications, online communities and instant messaging platforms, but these days it’s everywhere on the internet.

But why avatars ? well, just to make your app look a lot prettier and more user friendly. Also, these days, user avatars (or profile pictures) are everywhere on the internet; facebook, twitter, github and everywhere else. So why not add this feature in your app too ?.

So, If you would like to add avatars to your application’s users; there’s an easy way to do it. Users will be able to upload new avatars to their profile and also replace current avatar with new a one.

If you’ve already installed devise, added file validators, enabled active storage and also if you’ve already generated a users model; That’s great, you can skip the first steps. But for those of you beginner’s out there, you can read this tutorial to get the basics of authentication with devise, then proceed with the first steps.

The First Steps

Since we’ll use Devise for authentication and ‘file_validators’ to validate avatar attachment file uploads. We’ll add ‘devise’ and ‘file_validators’ to our Gemfile and run bundler to install the gems.

#File: Gemfile
gem 'devise'
gem 'file_validators'
bundle install

Then we’ll run devise’s generator to generate the necessary migrations and install devise.

rails g devise:install

Also, we can optionally run devise’s view generator to generate the views that already comes with devise.

rails g devise:views

Now let’s initialize active_storage, so that the avatar images can be uploaded. Rails 6 already comes with active storage, we don’t have to install the gem separately, we’ll just have to initialize it. We can do that by running the command below.

rails active_storage:install

Now we’ll create the new user model.

rails g devise user

Finally, lets run the migrations to complete the setup

rails db:migrate

Avatar Attachments

In the users model; i mounted the avatar attachment, with a ‘has_one_attached’ type of attachment. Also i added validations, so that the users can only upload png, jpg and gif files with a maximum file size limit of 5 Megabytes.

#File: app/models/user.rb
class User < ApplicationRecord

    devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :validatable
 ##...Avatar Attachment...##
    has_one_attached :avatar

## Validations
   validates :avatar, file_size: { less_than_or_equal_to: 5.megabytes },
              file_content_type: { allow: ['image/jpeg', 'image/png', 'image/gif'] }
end

Since, devise doesn’t generate the users controller, we’ll have to allow the new attachment parameter in our application controller.

class ApplicationController < ActionController::Base

   before_action :configure_permitted_parameters, if: :devise_controller?
   protected
      def configure_permitted_parameters
         devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:email, :password)}
         devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(:avatar, :email, :password, :current_password)}
      end
end

The Views

Devise already comes with views, you could also build your own views from scratch. But, For this tutorial. I’ll be using devise’s views so that everyone can follow along.

In my views, i don’t want to add the avatar upload field in the signup/registration page. Instead what i want is; that after the signup has completed, the user will be able to upload their avatars in their edit profile page.

So, in the edit registrations view, i added the the avatar file upload field.

#File: app/views/devise/registrations/edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>


<!--Avatar Upload Field-->
<div class="form-group">
<label class="col-sm-4 col-form-label">Avatar:
<% if current_user.avatar.present? %><br />Current: <%= current_user.avatar.filename.to_s %><% end %>
</label>
<div class="col-sm-8"><%= f.file_field :avatar, class: "form-control" %></div>
</div>
<!--Avatar Upload Field-->


<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: false, autocomplete: "email", class: "form-control" %>
</div>

<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>

<div class="form-group">
<%= f.label :password %> <i>(leave blank if you don't want to change it)
<%= f.password_field :password, autocomplete: "new-password", class: "form-control", placeholder: "New Password" %>
<% if @minimum_password_length %>
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>

<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-control", placeholder: "Confirm New Password" %>
</div>

<div class="form-group">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i>
<%= f.password_field :current_password, autocomplete: "current-password", class: "form-control", placeholder: "Current Password" %>
</div>

<div class="actions">
<%= f.submit "Update", class: "btn btn-warning btn-block" %>
</div>
<% end %>


<h3>Cancel my account</h3>

<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-danger btn-xs" %></p>

 

And wherever i want to show the uploaded avatar image, i’d just place a new image tag and with the appropriate image variant.

<% if current_user.avatar.present? %>
<%= image_tag(current_user.avatar.variant(resize_to_fill: [50, 50]), class: "rounded-circle") %>
<% else %>
<img alt="image" class="rounded-circle" src="/assets/default_avatar_small.jpg">
<% end %>

Final Result

So, this is what the end result looks like. Please note: i’m using an already existing template that i made for my last project; so, yours might not look exactly like this.

Photo source (Pexels): https://www.pexels.com/photo/young-lady-in-gray-jumper-with-decoration-near-face-6995703/

Railshero - Devise Edit User Profile
Railshero – Devise Edit User Profile

Final Thoughts

So, that was how to add user avatars with devise and active storage. You can also use other uploaders like carrierwave, paperclip, shrine, etc; the setup is pretty much similar. Please check out the links given below to get detailed info on the topics covered in this tutorial. That’s all folks, have a nice day.

https://guides.rubyonrails.org/active_storage_overview.html

https://api.rubyonrails.org/v6.1.4/classes/ActiveStorage/Variant.html

https://github.com/heartcombo/devise

https://docs.w3cub.com/rails~6.0/activestorage/variant

Leave a Reply Cancel reply

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

Tags

active record active storage assets assign to many associations attachment attachments authentication authorization avatar bootstrap cdn config database deploy deployments devise DRY environment variables file uploads Gemfile gems has_many helpers heroku index indexing initializer javascript pagination parameters postgres production public routes.rb ruby gem ruby gems search sendgrid server smtp stylesheets variants views voting

Recent Posts

  • Understanding the DRY Principle in Rails
  • Building Multi-tenant Applications with Rails
  • Rails Basics: Templating Engines
  • Deploying With Capistrano
  • Automated Testing in Rails

Archives

  • July 2023
  • June 2023
  • October 2021
  • September 2021
  • August 2021
  • July 2021

Categories

  • Active Record
  • Activity Logging
  • Apps
  • Assets
  • Attachments
  • Audio
  • Authentication
  • Authorization
  • Deployments
  • Error Pages
  • File Uploads
  • General
  • Heroku
  • Heroku
  • Pagination
  • Rails Basics
  • RubyGems
  • Search Engine Optimization
  • Search/Indexing
  • Testing
  • User Interface
  • Video
  • Views & Templating
  • Voting
  • Web Security
©2025 Railshero | Theme: Wordly by SuperbThemes
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.
Cookie SettingsAccept All
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Non-necessary
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
SAVE & ACCEPT