17

When adding attachments such as

has_one_attached :resume_attachment

saved files end up in the top level of the S3 bucket. How can I add them to subdirectories? For example, my old paperclip configuration could categorize in directories by model name.

Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101
  • Downvoters, please explain so I can improve the question. I haven't found a duplicate. If it is simply a bad idea please explain why. – Peter DeWeese Apr 18 '18 at 13:19
  • 1
    Sadly you can't, I look for this too but I think AS is too "young" for the moment and there aren't all options that you can find in alternatives. – coding addicted Apr 19 '18 at 12:07
  • 1
    There are few questions nearly duplicates on SO about this: https://stackoverflow.com/questions/49852567/how-to-upload-a-folder-using-activestorage-while-maintaining-original-folder-str; I don't understand the downvoters as well :( – coding addicted Apr 19 '18 at 12:11
  • @codingaddicted thanks. Nearly duplicates, but none duplicate. – Peter DeWeese Apr 19 '18 at 13:04
  • 1
    I totally agree, there are a lot specific aspects asked on SO that aren't covered by AS for the moment. For me you're question is 100% valid and I hope the AS team look at it and the other questions too. – coding addicted Apr 19 '18 at 13:25
  • 1
    Ha. The 6 downvote users were all removed. Some kind of mischief I suppose. – Peter DeWeese Apr 20 '18 at 13:41
  • The power of karma ;) – coding addicted Apr 20 '18 at 17:19

2 Answers2

5

You can not. There is only one option possible, at that time, for has_one_attached, has_many_attached macros that is :dependent. https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/attached/macros.rb#L30

see (maybe the reason why you have downvotes, but it is about "direct" upload so...) : How to specify a prefix when uploading to S3 using activestorage's direct upload?. The response is from the main maintainer of Active Storage.

Dinatih
  • 2,456
  • 1
  • 21
  • 21
0

Use a before_validation hook to set the desired key on S3 and the desired filename for the content disposition object properties on S3.

The key and filename properties on the attachment model make their way through to the ActiveStorage S3 gem and are converted into S3 key + content disposition object properties.


class MyCoolItem < ApplicationRecord
  has_one_attached :preview_image
  has_one_attached :download_asset

  before_validation :set_correct_attachment_filenames

  def preview_image_path
    # This key has to be unique across all assets. Fingerprint it yourself.
    "/previews/#{item_id}/your/unique/path/on/s3.jpg"
  end

  def download_asset_path
    # This key has to be unique across all assets. Fingerprint it yourself.
    "/downloads/#{item_id}/your/unique/path/on/s3.jpg"
  end
  
  def download_asset_filename
    "my-friendly-filename-#{item_id}.jpg"
  end

  def set_correct_attachment_filenames
    # Set the location on S3 for new uploads:
    preview_image.key = preview_image_path if preview_image.new_record?
    download_asset.key = download_asset_path if download_asset.new_record?

    # Set the content disposition header of the object on S3:
    download_asset.filename = download_asset_filename if download_asset.new_record?
  end
end
dtbaker
  • 4,679
  • 6
  • 28
  • 30