class Ratonvirus::Storage::ActiveStorage

Public Instance Methods

accept?(resource) click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 13
def accept?(resource)
  resource.is_a?(::ActiveStorage::Attached::One) ||
    resource.is_a?(::ActiveStorage::Attached::Many)
end
asset_path(asset) { |path| ... } click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 33
def asset_path(asset, &block)
  return unless block_given?
  return unless asset.is_a?(Array)

  ext = asset[0].filename.extension_with_delimiter
  case asset[1]
  when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
    # These files should be already locally stored but their permissions
    # can prevent the virus scanner executable from accessing them.
    # Therefore, a temporary file is created for them as well.
    io_path(asset[1], ext, &block)
  when Hash
    io = asset[1].fetch(:io)
    io_path(io, ext, &block) if io
  when ::ActiveStorage::Blob
    asset[1].open do |tempfile|
      prepare_for_scanner tempfile.path
      yield tempfile.path
    end
  end
end
asset_remove(asset) click to toggle source

This is actually only required for the dyncamic blob uploads but for consistency, it is handled for all the cases accordingly either by closing the tempfile of the upload which also removes the file when called with the bang method. For the IO references, the IO is closed which should trigger the file deletion by latest at the Rack or Ruby level during garbage collection. There is no guarantee that the file for which the IO was opened would be deleted beause the IO itself is not necessarily associated with an actual file.

# File lib/ratonvirus/storage/active_storage.rb, line 63
def asset_remove(asset)
  return unless asset.is_a?(Array)

  case asset[1]
  when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
    # This removes the temp file from the system.
    asset[1].tempfile.close!
  when Hash
    # No guarantee all references for the file are deleted.
    io = asset[1].fetch(:io)
    io.close
  when ::ActiveStorage::Blob
    # This deletes the dynamically uploaded blobs that might not be
    # associated with any record at this point. This ensures the blobs are
    # not left "hanging" in the storage system and the database in case
    # automatic file deletion is applied.
    asset[1].purge
  end
end
changed?(record, attribute) click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 8
def changed?(record, attribute)
  resource = record.public_send attribute
  !resource.record.attachment_changes[resource.name].nil?
end
process(resource, &block) click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 18
def process(resource, &block)
  return unless block_given?
  return if resource.nil?
  return unless resource.attached?

  change = resource.record.attachment_changes[resource.name]

  case change
  when ::ActiveStorage::Attached::Changes::CreateOne
    handle_create_one(change, &block)
  when ::ActiveStorage::Attached::Changes::CreateMany
    handle_create_many(change, &block)
  end
end

Private Instance Methods

handle_create_many(change, &block) click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 89
def handle_create_many(change, &block)
  change.send(:subchanges).each do |subchange|
    yield_processable_from(subchange, &block)
  end
end
handle_create_one(change, &block) click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 85
def handle_create_one(change, &block)
  yield_processable_from(change, &block)
end
yield_processable_from(change) { |processable([attachment, attachable])| ... } click to toggle source
# File lib/ratonvirus/storage/active_storage.rb, line 95
def yield_processable_from(change, &_block)
  attachable = change.attachable
  return unless attachable
  return if attachable.is_a?(::ActiveStorage::Blob)

  # If the attachable is a string, it is a reference to an already
  # existing blob. This can happen e.g. when the file blob is uploaded
  # dynamically before the form is submitted.
  attachable = change.attachment.blob if attachable.is_a?(String)

  yield processable([change.attachment, attachable])
end