4

I am using ActiveStorage for uploading PDFs and images. The PDFs need to be stored locally because of some privacy concerns, while the images need to be stored using Amazon S3. However, it looks like ActiveStorage only supports setting one service type per environment (unless you use the mirror functionality, which doesn't do what I need it to in this case).

Is there a way to use different service configs within the same environment? For example, if a model has_one_attached pdf it uses the local service:

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

And if another model has_one_attached image it uses the amazon service:

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""

3 Answers3

5

Rails 6.1 now supports this.

As per this article, you can specify the service to use for each attached:

class MyModel < ApplicationRecord
  has_one_attached :private_document, service: :disk
  has_one_attached :public_document,  service: :s3
end
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • 1
    Now, after RAILS 6.1 is released - it seems to be NOT to support multiple has_one_attached statements ! I got the ERROR message : Cannot configure service – Sven Kirsten Jan 08 '21 at 18:53
  • It seems to work for me. Was your service configured properly in `config/storage.yml`? – Samuel Sep 09 '21 at 14:35
1

ActiveStorage is great, but if you're in need of multiple service types per environment it currently won't work for you (as George Claghorn mentioned above). If you need an alternate option, I solved this problem by using Shrine.

The trick is to setup multiple 'stores' in your initializer:

# config/initializers/shrine.rb

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new('storage', prefix: 'uploads/cache'),
  pdf_files: Shrine::Storage::FileSystem.new('storage', prefix: 'uploads'),
  images: Shrine::Storage::S3.new(**s3_options)
}

And then use the default_storage plugin in each uploader (which you connect to a given model). Note that it won't work unless you specify the default_storage in both uploaders:

class PdfFileUploader < Shrine
  plugin :default_storage, cache: :cache, store: :pdf_files
end

class ImageFileUploader < Shrine
  plugin :default_storage, cache: :cache, store: :images
end
-1

Sorry, I’m afraid Active Storage doesn’t support this.

George Claghorn
  • 26,261
  • 3
  • 48
  • 48
  • 1
    There's an open pull request that looks like it'll be merged in at some point soon, however unfortunately not for the Rails 6.0.0 release https://github.com/rails/rails/pull/34935 – Tom Luce Jun 06 '19 at 16:22
  • 2
    It's merged since Oct.1, so Rails 6.1 should have it – lumpidu Dec 18 '19 at 10:53