avo-hq / avo

Build Ruby on Rails apps 10x faster
https://avohq.io
Other
1.43k stars 222 forks source link

Provide key for file upload #2890

Open rctneil opened 1 week ago

rctneil commented 1 week ago

Allow a way for a key to be passed in for a file as per the key option described here: https://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-file-io-objects

Is there a possible workaround for being able to specify the name of uploads for when they are stored at the source?

adrianthedev commented 1 week ago

I don't quite get the request. Can you please rephrase it or maybe make a screen recording or something?

rctneil commented 5 days ago

Ok, sorry. Let me try to explain my need.

I am building an extension to my app which requires one or more images uploading to each record. I have a spreadsheet of the records to be added. I also need to be able to cross reference the files that are uploaded directly from where they are stored, eg, the Amazon S3 bucket with the lines in my spreadsheet just by looking at the filenames being able to tell which record in my spreadsheet they belong to.

It looks like Active Storage provides a "key" option. When creating a file upload field type in Avo, it would be nice if there were 3 options:

  1. Auto generated key (default (exactly as it works now))
  2. A method on the model that provides a key name to use (maybe by joining the the "name" field with a random id or something) Whatever the user wants really.
  3. A text field that the user can type into specify the name (obviously with the user knowing that if an existing key is chosen then the file will get overwirtten).

Does that make more sense?

adrianthedev commented 5 days ago

It looks like Active Storage provides a "key" option.

Where is that option named key? I can't find it in the docs.

rctneil commented 5 days ago

The link has this snippet in it:

`There is an additional parameter key that can be used to specify folders/sub-folders in your S3 Bucket. AWS S3 otherwise uses a random key to name your files. This approach is helpful if you want to organize your S3 Bucket files better.

@message.images.attach( io: File.open('/path/to/file'), filename: 'file.pdf', content_type: 'application/pdf', key: "#{Rails.env}/blog_content/intuitive_filename.pdf", identify: false ) COPY This way the file will get saved in the folder [S3_BUCKET]/development/blog_content/ when you test this from your development environment. Note that if you use the key parameter, you have to ensure the key to be unique for the upload to go through. It is recommended to append the filename with a unique random key, something like:

def s3_file_key "#{Rails.env}/blog_content/intuitive_filename-#{SecureRandom.uuid}.pdf" end COPY @message.images.attach( io: File.open('/path/to/file'), filename: 'file.pdf', content_type: 'application/pdf', key: s3_file_key, identify: false )`

From this guide: https://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-file-io-objects

adrianthedev commented 4 days ago

Oh right, I missed it, the first time.

We can't tackle this right now. It shouldn't be very difficult to add. Would you like to give it a try?

Approach

Here is what you suggested and how we could implement it.

Add the key option to the fields

The API we are shooting for is this:

field :spreadsheet, as: :files, key: SOME_KEY

The SOME_KEY value will be forwarded through the key option all the way to the attach invocation.

rctneil commented 4 days ago

Yes, i'm just taking a look at it now.

Quick question: Are we taking the approach here that key: SOME_KEY will point to a method on the model?

adrianthedev commented 4 days ago

We could make that dynamic using the ExecutionContext. Here's a PR that makes an option callable so you know how to do it.

So we'd have two APIs:

# static
field :spreadsheet, as: :files, key: SOME_KEY

# dynamic
field :spreadsheet, as: :files, key: -> { record.some_method }