Shrine delete my source file

Hello!
I have similar problem as here
My code for reproduce this behavior.

# exec: $ ruby example_shrine.rb
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'rails'
  gem 'shrine'
end

require "shrine"
require "shrine/storage/file_system"

Shrine.storages = {
  # temporary
  cache: Shrine::Storage::FileSystem.new(
    File.expand_path('./public'),
    prefix: "uploads/cache"
  ),
  # permanent
  store: Shrine::Storage::FileSystem.new(
     File.expand_path('./public'),
    prefix: "uploads"
  ),
}

Shrine.plugin :upload_options, cache: { move: true }, store: { move: true }

Shrine.plugin :determine_mime_type

Shrine.plugin :instrumentation

Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data
Shrine.plugin :restore_cached_data

Shrine.plugin :validation_helpers
Shrine.plugin :derivatives


class ExampleUploader < Shrine
  Attacher.validate do
    validate_max_size 20.megabytes
  end
end

file = File.open(File.expand_path('./file.png'))
ExampleUploader.upload(file, :store)
# ./file.png has been deleted
binding.irb

I can confirm that with the example you have provided, the file is indeed disappearing.

now the question remains: (i) why is this happening, (ii) whether it is the expected behaviour, and if not (iii) what the relevant fix for this is.

Summary: The above code is simply the behaviour that is expected.

What is the fix?

  • Simply change move to false as below and it should work:

Here is the offending line:

Shrine.plugin :upload_options, cache: { move: false }, store: { move: false }
# change move to FALSE instead of true
# then your original file should remain
## file_system.rb
 def upload(io, id, move: false, **) # you had originally set move to be true:
        if move && movable?(io)
          move(io, path!(id))
        else
          IO.copy_stream(io, path!(id))
        end

        path(id).chmod(permissions) if permissions
      end

## if move is true this method gets called:
      def move(io, path)
        if io.respond_to?(:path)
          FileUtils.mv io.path, path
        else
          FileUtils.mv io.storage.path(io.id), path
          io.storage.clean(io.storage.path(io.id)) if io.storage.clean?
        end
      end

## And that method simply moves the file via a cut and paste.

Why is this happening?

In the script we are using the: Shrine::Storage::FileSystem.new but when you are using some production code, you will likely be using an amazon/azure etc. bucket. So the above behaviour will likely not happen when you are using an amazon storage bucket instead of simply using the file system.

(You might want to double check with some one more knowledgeable with Shrine, but i suspect the above might solve your problems)

Hope this helps.

This is what I need!
Thanks for the help