I created a monkey patch to set active storage service depending on settings in the database. (Code of the monkey patch bellow)
It works but it raises error ActiveRecord::RecordNotSaved (Failed to save the new associated _attachment) when I change the storage settings. Works again when I reload the rails server.
Monkey patch code in file lib/core_extensions/active_storage/dynamic_service_configuration.rb
## Dynamically sets Active storage service, depending on settings from the database
def set_config
storage_type = Setting.find_by_name('active_storage_type')
configs = {}
case storage_type
when 'disk'
configs[:disk] = {
service: 'Disk',
root: Rails.root.join('tmp/storage').to_s
}
ActiveStorage::Blob.services = ActiveStorage::Service::Registry.new(configs)
ActiveStorage::Blob.service = ActiveStorage::Blob.services.fetch(:disk)
when 's3'
configs[:s3] = {
service: 'S3',
access_key_id: Setting.find_by_name('active_storage_access_key'),
secret_access_key: Setting.find_by_name('active_storage_secret_key'),
bucket: Setting.find_by_name('active_storage_bucket'),
region: Setting.find_by_name('active_storage_region')
}
ActiveStorage::Blob.services = ActiveStorage::Service::Registry.new(configs)
ActiveStorage::Blob.service = ActiveStorage::Blob.services.fetch(:s3)
else
raise "Unknown storage type #{storage_type}"
end
end
# Service is dynamically configurable using the Setting active record model.
# Settings are saved in the database and is customizable from the super admin interface
# Extend the after initialize to change config each time
module CoreExtensions
module ActiveStorage
module DynamicServiceConfiguration
def self.prepended(base)
set_config
base.after_initialize do
set_config
end
end
end
end
end
# Monkey patch ActiveStorage Blob when loaded
ActiveSupport.on_load(:active_storage_blob) do
if ::ActiveStorage::Blob.included_modules.exclude?(CoreExtensions::ActiveStorage::DynamicServiceConfiguration)
::ActiveStorage::Blob.prepend CoreExtensions::ActiveStorage::DynamicServiceConfiguration
end
end
Inspired from https://github.com/rails/rails/blob/main/activestorage/lib/active_storage/engine.rb
initializer "active_storage.services"