Shrine: Shrine(2.7.0) is destroying my source file, when using it with rspec

Created on 6 Oct 2017  路  3Comments  路  Source: shrinerb/shrine

I've got a very strange issue :
During my test, Shrine is destroying the source file of my uploads ! The issue appear in 2.7.0 version, but I don't have problem with 2.5.0...
I'm using rails 5.0.6.

Here is my Factory :

FactoryGirl.define do
  factory :hunt do
    title               Faker::Lorem.word
    user                { FactoryGirl.create(:user) }
    description         Faker::Lorem.sentence
    follower            true
    number_of_follower  { rand(1..5) }
    comment             Faker::Lorem.sentence
    started_at          Time.now + 10.days
    finished_at         Time.now + 15.days
    acceptance_deadline Time.now + 9.days
    price               { rand(1..100) }
    exchange            true
    address             'test address'
    picture             { File.open("spec/fixtures/files/picture.jpg") }
    type                { FactoryGirl.create(:hunt_type) }
  end
end

My shrine initializer :

require "shrine"
require "shrine/storage/fog"
require "fog"


if Rails.env == 'test'
  require "shrine/storage/memory"

  Shrine.storages = {
    cache: Shrine::Storage::Memory.new,
    store: Shrine::Storage::Memory.new,
  }
else
  ovh_service = Fog::Storage.new(
    provider:             ENV['PROVIDER'],
    openstack_username:   ENV['OPEN_STAK_USERNAME'],
    openstack_api_key:    ENV['OPEN_STACK_API_KEY'],
    openstack_auth_url:   ENV['OPEN_STACK_AUTH_URL'],
    openstack_region:     ENV['OPEN_STACK_REGION'],
    openstack_temp_url_key: SecureRandom.urlsafe_base64(nil, false),
  )

  Shrine.storages[:store] = Shrine::Storage::Fog.new(
    connection: ovh_service,
    directory: ENV['OPEN_STACK_FOLDER_NAME'],
    expires: 24,
    type: 'public'
  )

  Shrine.storages[:cache] = Shrine::Storage::Fog.new(
    connection: ovh_service,
    directory: ENV['OPEN_STACK_FOLDER_NAME'],
    type: 'public'
  )
end

My uploader :

require "image_processing/mini_magick"

class ImageUploader < Shrine
  # plugins and uploading logic
  include ImageProcessing::MiniMagick
  plugin :activerecord
  plugin :cached_attachment_data # for forms
  plugin :upload_endpoint
  plugin :processing
  plugin :versions   # enable Shrine to handle a hash of files
  plugin :delete_raw # delete processed files after uploading
  plugin :validation_helpers
  plugin :determine_mime_type

 Attacher.validate do
   validate_extension_inclusion %w[jpg jpeg png gif]
   validate_mime_type_inclusion %w[image/jpeg image/png image/gif]
 end

  process(:store) do |io, context|
    original = io.download

    size_800 = resize_to_limit!(original, 800, 800) { |cmd| cmd.auto_orient } # orient rotated images
    size_500 = resize_to_limit(size_800, 500, 500)
    size_300 = resize_to_limit(size_500, 300, 300)
    size_150 = resize_to_limit(size_300, 150, 150)
    size_60  = resize_to_limit(size_150, 60, 60)

    { original: io, large: size_800, medium: size_500, card: size_300, little: size_150, small: size_60 }
  end
end

And my route :
mount ImageUploader.upload_endpoint(:cache) => "/images/upload"

I really don't know from where it can be from... Any idea ?

Thanks in advance !

Most helpful comment

The delete_raw plugin is deleting your test file. The reason why this happens on version 2.7.0 and not before is that the delete_raw plugin was recently fixed to also work on File objects in addition to Tempfile objects.

There are several solutions. One solution is to configure delete_raw plugin to only delete raw files that are uploaded to permanent storage:

plugin :delete_raw, storages: [:store]

Another solution is to provide a StringIO object in your factory definition:

require "stringio"

FactoryGirl.define do
  factory :hunt do
    # ...
    picture  { StringIO.new(File.binread("spec/fixtures/files/picture.jpg")) }
    # ...
  end
end

I don't like how magical the delete_raw and similar plugins are, it would be better specifying deletion was opt-in instead of opt-out, such as passing a :delete_raw option on uploading. I will rethink this in the future, but for now these two options are the idiomatic solutions.

All 3 comments

The delete_raw plugin is deleting your test file. The reason why this happens on version 2.7.0 and not before is that the delete_raw plugin was recently fixed to also work on File objects in addition to Tempfile objects.

There are several solutions. One solution is to configure delete_raw plugin to only delete raw files that are uploaded to permanent storage:

plugin :delete_raw, storages: [:store]

Another solution is to provide a StringIO object in your factory definition:

require "stringio"

FactoryGirl.define do
  factory :hunt do
    # ...
    picture  { StringIO.new(File.binread("spec/fixtures/files/picture.jpg")) }
    # ...
  end
end

I don't like how magical the delete_raw and similar plugins are, it would be better specifying deletion was opt-in instead of opt-out, such as passing a :delete_raw option on uploading. I will rethink this in the future, but for now these two options are the idiomatic solutions.

Hello @janko!
I use shrine 3.2.1 and have this problem, but i not use delete_raw plugin.
I have derivatives plugin. What argument pass to plugin :derivatives, that disable delete source file?

Hi @Yegorov , please ask this question on the Discourse forum for questions! https://discourse.shrinerb.com/

I am not sure exactly what you are doing, but you may be running into what's documented here. But please don't discuss this anymore on this Github issue, please use the discourse forum -- or if you are confident it's a bug, please file a separate ticket with a complete description of the problem and a reproducible test case. Thanks for using shrine and providing feedback!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abevoelker picture abevoelker  路  5Comments

brunowego picture brunowego  路  3Comments

Sohair63 picture Sohair63  路  3Comments

musaffa picture musaffa  路  7Comments

technodrome picture technodrome  路  4Comments