Derivatives with original file name

I’m struggling to get derivatives to display correctly with the original filename.
Long term I’d like the location to be:

[class_name,
identifier,
derivative,
filename
].compact.join("/")

But just at the basic level, following the paperclip migration guide and other docs…when I use:

class ImageUploader < Shrine
  def generate_location(io, record: nil, name: nil, **)
    [ storage_key,
      record && record.class.name.underscore,
      record && record.id,
      super,
      io.original_filename ].compact.join("/")
  end
end

It works as expected showing up at
store/gallery_image/624/[uuid]/[original name].

But when using derivatives

class ImageUploader < Shrine
      def generate_location(io, record: nil, name: nil, **)
        [ storage_key,
          record && record.class.name.underscore,
          record && record.id,
          super,
          io.original_filename ].compact.join("/")
      end
      
      plugin :derivatives

      Attacher.derivatives do |original|
        magick = ImageProcessing::MiniMagick.source(original)
        {
          large:  magick.resize_to_limit!(800, 800),
          medium: magick.resize_to_limit!(500, 500),
          small:  magick.resize_to_limit!(300, 300)
        }
      end
    end

it gives me

undefined method original_filename’ for #<Tempfile:0x00007ff1f691a628>

Would love any help, thanks so much.

When derivatives are being uploaded, the original filename unfortunately won’t be accessible in the uploader. The #generate_location method will receive the :derivative keyword argument holding the derivative name, which you’ll likely want to use, because your current #generate_location returns the same path for both original file and derivatives, so they would just overwrite each other. The original filename is attribute on the original file, which is not passed when uploading a derivative.