Today I want to tell you how to do global preprocessing of uploaded files in ActiveStorage
. Unfortunately ActiveStorage
design doesn’t provide this feature out of the box, or I haven’t found any information about it. But sometimes you may need to process attachments for all models in a project.
To achieve this goal, we need to override several methods of singleton class of ActiveStorage::Blob
class, in my version (rails 6.1) they are build_after_upload
, build_after_unfurling
and upload
. To do this, let’s make a module, for example in lib/active_storage/blob_preprocessor.rb
:
# lib/active_storage/blob_preprocessor.rb
module ActiveStorage
module BlobPreprocessor
def build_after_upload(io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil) #:nodoc:
preprocess!(io)
super(io: io, filename: filename, content_type: content_type, metadata: metadata, service_name: service_name, identify: identify, record: record)
end
def build_after_unfurling(key: nil, io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil) #:nodoc:
preprocess!(io)
super(key: key, io: io, filename: filename, content_type: content_type, metadata: metadata, service_name: service_name, identify: identify, record: record)
end
def upload(io, identify: true)
preprocess!(io)
super(io, identify: identify)
end
def preprocess!(io)
# Here we can do everything with io Tempfile, but we should not change its path.
# Thats why this method doesn't return new Tempfile.
end
end
end
Finally we have to include this module in ActiveStorage::Blob.singleton_class
. We can do this in config/application.rb
#...
config.to_prepare do
ActiveStorage::Blob.singleton_class.include ActiveStorage::BlobPreprocessor
end
#...