DEV Community

Daveyon Mayne 😻
Daveyon Mayne 😻

Posted on

User's initial as an avatar image

Image with the letter 'D'

Basecamp does something like this but I do not know exactly how they've done it. This is my take on using an image for the user's avatar, uploaded using Active Storage.

My profile model is setup with an has_one_attached:

# profile.rb

has_one_attached :avatar
belongs_to :user

Enter fullscreen mode Exit fullscreen mode

User model is not important here but it looks like this:

# user.rb

has_one :profile

Enter fullscreen mode Exit fullscreen mode

The logic is that once the user has registered with their name, we generate the image initial then upload it.


def generate_avatar(user)
  # The first character from the user's name.
  # Basecamp does some extra checks to check for numbers
  # and alphabet from the name. When invalid, they
  # return a question mark: ?
  initial = user.profile.name.first.upcase

  # A colour that will not change for the user: red, green, hex value etc
  colour = user.default_colour

  # A HTML markup with background color; inline or in the css file
  html = "<div style='background:#{colour};width:280px;height:280px' class='custom_avatar'><span>#{initial}</span></div>"

  # See rest of post
  kit = IMGKit.new(html, :width => 280, :quality => 50)

  # A custom stylesheet
  kit.stylesheets << "#{Rails.root}/app/assets/stylesheets_custom/custom_avatar.css"

  # Store image in a temp folder
  file_path = Tempfile.new(["file", '.jpg']).path
  kit.to_file(file_path)

  # Upload the image
  user.profile.avatar.attach(io: File.open(file_path), filename: 'avatar.jpg')
end

Enter fullscreen mode Exit fullscreen mode

The setup

Gemfile.rb:

# https://github.com/csquared/IMGKit
gem 'imgkit'
gem 'wkhtmltoimage-binary'
Enter fullscreen mode Exit fullscreen mode

Run bundle install to install the gems above. I'm using IMGKit.

Custom Stylesheet

I put this in app/stylesheets_custom/*


* {
  margin: 0;
  padding: 0;
}
.custom_avatar {
  width: 280px;
  height: 280px;
  padding: 0;
  margin: 0;
  font-size: 8rem;
  font-weight: bold;
  color: white;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
}

Enter fullscreen mode Exit fullscreen mode

For reusable methods, I create a module and place in: controllers/concerns/*:

# user_avatar_image.rb

module UserAvatarImage

  def random_colour
    ["#A9294F", "#ED6663", "#389393", "#D82148", "#8C5425", "#6F38C5"].sample
  end

  def generate_avatar(user)
    # The first character from the user's name
    initial = user.profile.name.first.upcase

    # A colour that will not change for the user: red, green, hex value etc
    colour = user.default_colour

    # A HTML markup with background color; inline or in the css file
    html = "<div style='background:#{colour};width:280px;height:280px' class='custom_avatar'><span>#{initial}</span></div>"

    # See rest of post
    kit = IMGKit.new(html, :width => 280, :quality => 50)

    # A custom style sheet
    kit.stylesheets << "#{Rails.root}/app/assets/stylesheets_custom/custom_avatar.css"

    # Store image in a temp folder
    file_path = Tempfile.new(["file", '.jpg']).path
    kit.to_file(file_path)

    # Upload the image
    user.profile.avatar.attach(io: File.open(file_path), filename: 'avatar.jpg')
  end
end

Enter fullscreen mode Exit fullscreen mode

The Flow

During user registration, random_colour is used to set a random colour. Next, we call generate_avatar(resource) to generate and upload the image. You would call generate_avatar every time the user changes their name 😉

Feel free to to modify the font size and dimensions for the image. Enjoy!

Top comments (0)