Migrating from Carrierwave to ActiveStorage in Rails

For the Video Upload Platform series that I have been working on (Sorry I haven’t updated in a bit), I had been using Carrierwave to manage the file uploads. It also has a bunch of plugins/gems available to help with some tasks, however I wanted to move the series more into as “What is actually happening” set of posts. For this reason, I have decided to migrate that project from using Carrierwave to using ActiveStorage, since that has been released somewhat recently and is build into Rails.

If you have been following along in that series, then it should be pretty straight forward using the details I’m about to go into. If not, thats ok too, it should still be pretty familiar to you. At any rate lets get started!

The first thing we want to make sure is that we are update to date with Rails. If you have a specific version set in your Gemfile, remove that, or update it to the latest:

# Gemfile

- gem "rails", "~> 5.1.6
+ gem "rails"

One we have that updated, we just need to bundle the project to pull all the new fun in

bundle

Ok great. Now we want to add the ActiveStorage migrations and configure the set up to use local storage for our example. Do this by running the following command

bundle exec rails active_storage:install
bundle exec rake db:migrate

Great, now we should have our database migrated to contain the ActiveStorage tables. Let create the proper config file that ActiveStorage uses now. Create the file config/storage.yml and paste in the following YAML:

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

This tells ActiveStorage to store things locally. If you are interested in using some type of other storage methods, check out the ActiveStorage Overview page. We only have one more configuration step to go, and we should be good. Add the following line to your config/environments/development.rb file (test.rb and production.rb) as well if you want:

config.active_storage.service = :local

Now that we have ActiveStorage all set up, we can go ahead and update our model to migrate from Carrierwave to ActiveStorage. I will show our model and the line we want to remove and add:

class Video < ApplicationRecord
-  mount_uploader :file, VideoUploader
+  has_one_attached :file
end

As you can see, we no longer are going to use the CarrierwaveUploader. We should now be able to upload files using the same controller and form uploads that we had already created. The last thing we need to change however, is the view. We will pass the url for the upload using some built-in Rails helpers. In the app/views/videos/show.html.erb file, we need to make this change:

<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @video.title %>
</p>

<p>
  <strong>File:</strong>
-  <video controls width="640" height="480" src="<%= @video.file.url %>"></video>
+  <video controls width="640" height="480" src="<%= url_for(@video.file) %>"></video>
</p>

<%= link_to 'Edit', edit_video_path(@video) %> |
<%= link_to 'Back', videos_path %>

The last piece that we need to add in, which I will do in another post, is the ability to do the background Transcoding, that we were getting out of the box with the carrierwave-video gem, but this should get us starting with using ActiveStorage instead of Carrierwave.

Let me know if you have any thoughts in the comments below, or run into any issues. Thanks!

1 thought on “Migrating from Carrierwave to ActiveStorage in Rails

  1. Hello Randy!

    Thanks for a great post!

    We run a not-for-profit social media community at breakdiving.io. We launched in 2019 with image uploads via Carrierwave, S3, and Heroku.

    We’d like to switch to ActiveStorage, but we don’t know how to do so in a way that doesn’t destroy all the photo uploads we already have, and that can still display the photos that have already been uploaded.

    Could you please help us to better understand how we can upgrade without losing everything?

    Thanks much!
    -Monroe

Leave a Reply

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