Today I would like to show you how to implement global preprocessing of uploaded files in Rails. Unfortunately, ActiveStorage does not make it possible to do this simply and explicitly, or I just did not find any information about it.
However, we can implement global preprocessing of files uploaded to ActiveStorage. To do this, we can use a frankly bad technique, we can redefine three methods in ActiveStorage::Blob. Here they are build_after_upload, build_after_unfolding and upload. Here I mean Rails 6.1.
# 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
endAnd finally, we need to patch the main class.
# config/application.rb
#...
config.to_prepare do
ActiveStorage::Blob.singleton_class.include ActiveStorage::BlobPreprocessor
end
#...