Rails – Carrierwave: Remove avatar and multiple files from S3

When a User destroys a record, what’s the point of keeping the uploaded files/images with Carrierwave on S3?

It’s wasted storage space. You need to be able to remove images and files from your Model.

In this tutorial, we will see how to use the Carrierwave method :remove_avatar to delete a file uploaded on S3 from your Rails app. We will also fix the problem of leftover empty directories.

1. Delete avatar and multiple Carrierwave files from S3 on Model destroy

Carrierwave provides a convenient method for removing uploaded files if a checkbox is checked. We will use and adapt it to delete file from S3 after the Model has been destroyed.

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader

  before_destroy :clean_s3

  def clean_s3
    avatar.thumb.remove! # if you have thumb version or any other version
  rescue Excon::Errors::Error => error
    puts "Something gone wrong"

This code comes from this nice StackOverflow answer.

To be complete, let’s say your model stores several files like Word documents and PDF, and not images avatar like the example on the docs, and you have the line mount_uploaders :attachments, AttachmentUploader in your model.

You’ll want to iterate through each attachment to remove it one at a time. Here is how:

def clean_s3
rescue Excon::Errors::Error => error
  puts "Couldn't be removed"


2. Delete empty directories

After implementing step 1 of this Carrierwave tutorial and destroying the object, you’ll notice that empty directories remain in the tmp cache directory.

While unpleasant, it’s not really a problem unless you have a very large amount of them.

But to keep things tidy, let’s see how to remove them. We will implement this a simple version of this solution from the wiki.

Your AttachmentUploader will look like this:

class AttachmentUploader < CarrierWave::Uploader::Base
  after :remove, :delete_empty_upstream_dirs # Clean up empty directories when the files in them are deleted

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir

  def delete_empty_upstream_dirs
    path = ::File.expand_path(store_dir, root)
    Dir.delete(path) # fails if path not empty dir, beware ".DS_Store" when in development  
  rescue SystemCallError
    true # nothing, the dir is not empty