diff --git a/app/controllers/active_storage_db/files_controller.rb b/app/controllers/active_storage_db/files_controller.rb index bd6ae7c..a2635d9 100644 --- a/app/controllers/active_storage_db/files_controller.rb +++ b/app/controllers/active_storage_db/files_controller.rb @@ -16,7 +16,7 @@ def show def update if (token = decode_verified_token) - file_uploaded = upload_file(token, body: request.body) + file_uploaded = upload_file(token) head(file_uploaded ? :no_content : unprocessable) else head(:not_found) @@ -54,7 +54,7 @@ def serve_file(key, content_type:, disposition:) send_data(db_service.download(key), options) end - def upload_file(token, body:) # rubocop:disable Naming/PredicateMethod + def upload_file(token) # rubocop:disable Naming/PredicateMethod return false unless acceptable_content?(token) db_service.upload(token[:key], request.body, checksum: token[:checksum]) diff --git a/lib/active_storage/service/db_service.rb b/lib/active_storage/service/db_service.rb index 3628532..8e89c23 100644 --- a/lib/active_storage/service/db_service.rb +++ b/lib/active_storage/service/db_service.rb @@ -90,7 +90,7 @@ def url_for_direct_upload(key, expires_in:, content_type:, content_length:, chec content_type: content_type, content_length: content_length, checksum: checksum, - service_name: respond_to?(:name) ? name : "db" + service_name: service_name_for_token }, expires_in: expires_in, purpose: :blob_token @@ -108,12 +108,20 @@ def headers_for_direct_upload(_key, content_type:, **) private + def service_name_for_token + respond_to?(:name) ? name : "db" + end + def adapter_sqlite? - @adapter_sqlite ||= active_storage_db_adapter_name == "SQLite" + return @adapter_sqlite if defined?(@adapter_sqlite) + + @adapter_sqlite = active_storage_db_adapter_name == "SQLite" end def adapter_sqlserver? - @adapter_sqlserver ||= active_storage_db_adapter_name == "SQLServer" + return @adapter_sqlserver if defined?(@adapter_sqlserver) + + @adapter_sqlserver = active_storage_db_adapter_name == "SQLServer" end def active_storage_db_adapter_name @@ -131,7 +139,7 @@ def generate_url(key, expires_in:, filename:, content_type:, disposition:) key: key, disposition: content_disposition, content_type: content_type, - service_name: respond_to?(:name) ? name : "db" + service_name: service_name_for_token }, expires_in: expires_in, purpose: :blob_key diff --git a/lib/active_storage/service/db_service_rails70.rb b/lib/active_storage/service/db_service_rails70.rb index 18e15a7..f4943cc 100644 --- a/lib/active_storage/service/db_service_rails70.rb +++ b/lib/active_storage/service/db_service_rails70.rb @@ -6,11 +6,13 @@ def compose(source_keys, destination_key, **) buffer = nil comment = "DBService#compose" source_keys.each do |source_key| - data = ::ActiveStorageDB::File.annotate(comment).find_by!(ref: source_key).data + record = ::ActiveStorageDB::File.annotate(comment).find_by(ref: source_key) + raise ActiveStorage::FileNotFoundError unless record + if buffer - buffer << data + buffer << record.data else - buffer = +data + buffer = +record.data end end ::ActiveStorageDB::File.create!(ref: destination_key, data: buffer) if buffer diff --git a/lib/tasks/active_storage_db_tasks.rake b/lib/tasks/active_storage_db_tasks.rake index 30b10d3..b827af9 100644 --- a/lib/tasks/active_storage_db_tasks.rake +++ b/lib/tasks/active_storage_db_tasks.rake @@ -5,22 +5,25 @@ module ActiveStorage module_function def print_blob_header(digits: 0) - puts ['Size'.rjust(8), 'Date'.rjust(18), 'Id'.rjust(digits + 2), ' Filename'].join + puts ["Size".rjust(8), "Date".rjust(18), "Id".rjust(digits + 2), " Filename"].join end def print_blob(blob, digits: 0) size = (blob.byte_size / 1024).to_s.rjust(7) - date = blob.created_at.strftime('%Y-%m-%d %H:%M') + date = blob.created_at.strftime("%Y-%m-%d %H:%M") puts "#{size}K #{date} #{blob.id.to_s.rjust(digits)} #{blob.filename}" end end end namespace :asdb do - desc 'ActiveStorageDB: list attachments ordered by blob id desc' + desc "ActiveStorageDB: list attachments ordered by blob id desc" task list: [:environment] do |_t, _args| query = ActiveStorage::Blob.order(id: :desc).limit(100) - digits = query.ids.inject(0) { |ret, id| size = id.to_s.size; [size, ret].max } + digits = query.ids.inject(0) { |ret, id| + size = id.to_s.size + [size, ret].max + } ActiveStorage::Tasks.print_blob_header(digits: digits) query.each do |blob| @@ -28,14 +31,14 @@ namespace :asdb do end end - desc 'ActiveStorageDB: download attachment by blob id' + desc "ActiveStorageDB: download attachment by blob id" task :download, [:blob_id, :destination] => [:environment] do |_t, args| blob_id = args[:blob_id]&.strip destination = args[:destination]&.strip || Dir.pwd - abort('Required arguments: source blob id, destination path') if blob_id.blank? || destination.blank? + abort("Required arguments: source blob id, destination path") if blob_id.blank? || destination.blank? blob = ActiveStorage::Blob.find_by(id: blob_id) - abort('Source file not found') unless blob + abort("Source file not found") unless blob destination = "#{destination}/#{blob.filename}" if Dir.exist?(destination) dir = File.dirname(destination) @@ -45,20 +48,23 @@ namespace :asdb do puts "#{ret} bytes written - #{destination}" end - desc 'ActiveStorageDB: search attachment by filename (or part of it)' + desc "ActiveStorageDB: search attachment by filename (or part of it)" task :search, [:filename] => [:environment] do |_t, args| filename = args[:filename]&.strip - abort('Required arguments: filename') if filename.blank? + abort("Required arguments: filename") if filename.blank? - blobs = ActiveStorage::Blob.where('filename LIKE ?', "%#{filename}%").order(id: :desc) + blobs = ActiveStorage::Blob.where("filename LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(filename)}%").order(id: :desc) if blobs.any? - digits = blobs.ids.inject(0) { |ret, id| size = id.to_s.size; [size, ret].max } + digits = blobs.ids.inject(0) { |ret, id| + size = id.to_s.size + [size, ret].max + } ActiveStorage::Tasks.print_blob_header(digits: digits) blobs.each do |blob| ActiveStorage::Tasks.print_blob(blob, digits: digits) end else - puts 'No results' + puts "No results" end end end diff --git a/spec/integration/attachments_spec.rb b/spec/integration/attachments_spec.rb index d292791..692767b 100644 --- a/spec/integration/attachments_spec.rb +++ b/spec/integration/attachments_spec.rb @@ -19,6 +19,8 @@ ActiveStorage.touch_attachment_records = false example.run ActiveStorage.touch_attachment_records = touch_option + else + example.run end end