3

Background
I am using file system storage, with the Shrine::Attachment module in a model setting (my_model), with activerecord (Rails). I am also using it in a direct upload scenario, therefore i need the response from the file upload (save to cache).

my_model.rb

class MyModel < ApplicationRecord
   include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
   omitted relations & code...
end

my_controller.rb

def create
  @my_model = MyModel.new(my_model_params)
  # currently creating derivatives & persisting all in one go
  @my_model.image_derivatives! if @my_model.image 

  if @my_model.save
    render json: { success: "MyModel created successfully!" }
  else
    @errors = @my_model.errors.messages
    render 'errors', status: :unprocessable_entity
  end

Goal
Ideally i want to clear only the cached file(s) I currently have hold of in my create controller as soon as they have been persisted (the derivatives and original file) to permanent storage.
What the best way is to do this for scenario A: synchronous & scenario B: asynchronous?

What i have considered/tried
After reading through the docs i have noticed 3 possible ways of clearing cached images:
1. Run a rake task to clear cached images.

I really don't like this as i believe the cached files should be cleaned once the file has been persisted and not left as an admin task (cron job) that cant be tested with an image persistence spec

# FileSystem storage file_system = Shrine.storages[:cache] file_system.clear! { |path| path.mtime < Time.now - 7*24*60*60 } # delete files older than 1 week

2. Run Shrine.storages[:cache] in an after block

Is this only for background jobs?

attacher.atomic_persist do |reloaded_attacher| # run code after attachment change check but before persistence end

3. Move the cache file to permanent storage

I dont think I can use this as my direct upload occurs in two distinct parts: 1, immediately upload the attached file to a cached store then 2, save it to the newly created record.
plugin :upload_options, cache: { move: true }, store: { move: true }

Are there better ways of clearing promoted images from cache for my needs?

orion
  • 504
  • 1
  • 5
  • 17
  • 2
    If you set up cached files to be automatically deleted once they promoted to permanent storage, you're still not guaranteed not to have any cached files in production. This is because not all files uploaded to temporary storage might get attached. If the form has validation errors, the user couold change their mind and upload another image, in which case the original image was not attached. The same thing can happen with direct uploads. – Janko Jan 07 '20 at 15:09

1 Answers1

1

Synchronous solution for single image upload case:

def create
  @my_model = MyModel.new(my_model_params)
  image_attacher = @my_model.image_attacher               
  image_attacher.create_derivatives                       # Create different sized images
  image_cache_id = image_attacher.file.id                 # save image cache file id as it will be lost in the next step
  image_attacher.record.save(validate: true)              # Promote original file to permanent storage
  Shrine.storages[:cache].delete(image_cache_id)  # Only clear cached image that was used to create derivatives (if other images are being processed and are cached we dont want to blow them away)
end
orion
  • 504
  • 1
  • 5
  • 17
  • 5
    Note that you can simplify the code like this: `cached_image = image_attacher.file` and then doing `cached_image.delete`. – Janko Jan 07 '20 at 15:05