Access attacher / record inside upload_options / url_options

Hello @janko

Using Shrine with ActiveRecord using background plugin for promotion.

I’m currently using the same attacher for two activerecord models (an Attachment uploader, both models have attachments) and i’m right now in a problem as i need to upload some files with public acl.

I know i don’t have access on the upload_options and url_options plugin to the attacher/record, and although maybe is not the best design, i understand i can pass the record to the “context” of those plugins, so for example to check the record class to know if that file should be upload as public or private.

The thing is i don’t get how i should pass the records as part of the context, being almost every upload/promotion is done automatically by the activerecord integration.

Is maybe on the background plugin on the atomic_promote call?

Hope my problem is understood, thanks as always!

Hello, still learning about this gem, so I’m not sure if this is a good idea but I’ll share one of my notes in the code snippet below.

Assuming you’re on s3, you can basically access the client. Since it’s expensive to do that, I was thinking of storing the acl status in my db. Then the acl could be toggle to public after upload (with the s3 client).

def private_or_public_url
  # Note: I may use this
  # Here, pdf is my virtual column for pdf_data
  # pdf.storage.client.get_object_acl({bucket: ENV.fetch('MY_BUCKET_NAME'), key: pdf.id})[:grants].first[:permission]
  # => 'READ' (public) or 'FULL_CONTROL' (semi-public)
  # if public, use `pdf.url(public: true)`
  #pdf.url(public: true)
  if pdf.nil?
    return '#NOT_FOUND'
  end
  pdf.url(expires_in: Integer(1.week))
end

Hello, thanks for your help!

You give me a tip here and eventually i can change the acl on the background job after promotion, although i feel it will be better to just do the check on the plugin configurations, both for upload and url.

Hello @janko, sorry for bothering again with this one. Not sure if the problem was undeerstood, or if you can help me to figure out how should i pass the context to the plugins.
Thanks in advance

Hi David, apologies for my delay, I was busy with some other open source work.

In order to set acl: "public-read" for certain records/files, I would recommend passing the ACL directly, and specifying in the metadata that the file is public:

# ...
if some_condition
  attacher.atomic_promote(
    upload_options: { acl: "public-read" },
    metadata: { "public" => true },
  )
else
  attacher.atomic_promote
end

Then in your url_options plugin you can generate a public URL based on the public metadata that you’ve set:

Shrine.plugin :url_options, store: -> (file, options) do
  { public: true } if file.metadata["public"]
end

Hello @janko

Great, so i should add the public read flag it in the background job while promoting the file as i was thinking.

Thank you so much!