Migrating from Paperclip to Active Storage in Rails

Migrating from one file attachment library to another can be a challenging task, but with Rails’ built-in Active Storage, the process becomes much smoother.

Step 1: Preparing the Application

Install the Active Storage gem by adding it to your Gemfile:

1
gem 'activestorage'

Run the bundle install command:

1
bundle install

Run the active_storage:install command to generate the necessary migrations:

1
rails active_storage:install

Configure Active Storage by setting up the desired storage service (local or cloud-based) in config/storage.yml.

Configure the desired storage service in config/environments/development.rb and config/environments/production.rb:

1
config.active_storage.service = :local # or :amazon, :google, etc.

Step 2: Adapting the Model

Update the model that uses Paperclip to switch to Active Storage. For example, if you have a model named Attachment with a Paperclip attachment named file, you would make the following changes:

1
2
3
4
5
6
7
class Attachment < ApplicationRecord
  # Remove Paperclip attachment declaration
  # has_attached_file :file, ...

  # Add Active Storage attachment declaration
  has_one_attached :file
end

Update the model associations and validations related to the attachment. For example, if you have a User model that has many attachments with Paperclip, you would modify it as follows:

1
2
3
4
5
6
7
class User < ApplicationRecord
  # Remove the Paperclip association
  # has_many :attachments, as: :attachable

  # Add the Active Storage association
  has_many_attached :attachments
end

Step 3: Updating the Views and Controllers

Replace any Paperclip-specific view code with Active Storage equivalents. For example, if you were displaying an image using Paperclip, you would modify the view code as follows:

1
2
3
4
5
<!-- Before -->
<%= image_tag @attachment.file.url %>

<!-- After -->
<%= image_tag url_for(@attachment.file) %>

Adjust the view code to render the appropriate URLs for Active Storage attachments. For example, if you had a download link for a Paperclip attachment, you would update it as follows:

1
2
3
4
5
<!-- Before -->
<%= link_to 'Download', @attachment.file.url %>

<!-- After -->
<%= link_to 'Download', url_for(@attachment.file) %>

Modify the controller actions to handle file uploads using Active Storage. For example, if you had a create action in your controller that handled file uploads with Paperclip, you would update it as follows:

1
2
3
4
5
6
7
8
9
def create
  @attachment = Attachment.new(attachment_params)
  @attachment.file.attach(params[:attachment][:file]) # Attach the file using Active Storage
  if @attachment.save
    # ...
  else
    # ...
  end
end

Step 4: Data Migration

Create a new data migration to transfer existing Paperclip attachments to Active Storage. For example:

1
$ rails generate migration MigratePaperclipAttachmentsToActiveStorage

In the generated migration file, write the migration code to transfer the attachments. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MigratePaperclipAttachmentsToActiveStorage < ActiveRecord::Migration[6.1]
  def up
    Attachment.find_each do |attachment|
      attachment.file.attach(io: File.open(attachment.file.path), filename: attachment.file_file_name)
    end
  end

  def

 down
    # If needed, implement a rollback method
  end
end

Step 5: Testing and Cleanup

Update existing tests or add new tests to ensure proper functionality after the migration.

Remove any Paperclip-related code, migrations, or configuration files from the project.