Shrine 3: Correct way to modify original file

First: Thanks so much for Shrine, it’s been an amazing tool for my Ruby projects.

We are migrating a large project from Shrine 2 to 3, and switching over to the new Derivatives plugin.

When processing an uploaded file, we do keep the original files, but we still need to strip metadata/EXIF data from originals for legal reasons (because people do things like upload avatar images that contain their current coordinates in EXIF).

Inside the Attacher.derivatives block, will changes to the original file be persisted correctly? There does not appear to be an officially documented way to adjust the original before handing it off to the Derivatives plugin. Would Attacher#sequel_before_save possibly be the best place to do it?

While we could store the uploaded file, then call some kind of secondary process to strip and re-save the original each time, this isn’t ideal because we would still have had their potentially personal data in our possession for longer than the period of an HTTP request (and that process could get accidentally turned off, etc. Better to not build it if we can.)

Hi, I’m glad to hear that Shrine is useful for you :slight_smile:

If you want to process the original file during the HTTP request, I would recommend grabbing the file before it’s assigned as the attachment, and processing it there, and then proceeding the assignment with the processed file.

If you’re using direct uploads, you can download the file, process it, then replace it:

uploaded_file = Shrine.uploaded_file(params[:photo][:image])
uploaded_file.download do |original|
  strip_metadata(original.path) # replace with your code
  uploaded_file.replace(original)
end

Alternatively, inside the Attacher.derivatives block the original file will already be uploaded, and the downloaded copy is yielded to the block, so changing there would require re-uploading. You could still do it as follows:

Attacher.derivatives do |original|
  strip_metadata(original.path) # replace with your code
  file.replace(original) # replaces original file in-place
  # ... continue processing derivatives ...
end

Just make sure that the changes to the file are always flushed to disk, if you’re doing metadata stripping in Ruby, and that the file is rewinded before re-uploading it. It’s also a good idea to call #open on the uploaded file in case you’ve modified the file in-place with a command-line tool, which reopens the file thus refreshing the file descriptor (as not doing this could cause problems with aws-sdk-s3 upload for some reason).