require 'fiona7/attribute_writers/attribute_writer' module Fiona7 module AttributeWriters class BinaryAsBinary < AttributeWriter def call(value, claimed_type=nil) if value.kind_of?(File) self.special_upload_handling(self.attr_name, value) elsif value.kind_of?(ActionDispatch::Http::UploadedFile) self.special_upload_uploaded_handling(self.attr_name, value) elsif value.nil? self.obj.set(self.attr_name, '') elsif value.kind_of?(Hash) source_blob_id = value["id"] || value["id_to_copy"] filename = value["filename"] content_type = value["content_type"] # There is a little bit of magic behind this. # This will pass some data directly to the crul_obj # bypassing self.obj.set(), but calling self.obj.save # afterwards still persists the data correctly # # This works the same way as Reactor::Tools::Uploader Fiona7::Builder::LazyBlobCopier.new({ destination_obj: self.obj, attr_name: self.attr_name, source_blob_id: source_blob_id, filename: filename, content_type: content_type }).call # NOTE: no self.obj.set() required here else raise Scrivito::ClientError.new("Invalid input for binary field", 422) end end protected def special_upload_handling(attribute_name, file) if !self.obj.binary? # standard handling! self.obj.set(attribute_name.to_s, self.upload_file(file)) else ext = ::File.extname(file.path).to_s[1..-1] self.obj.upload(file, ext) end end def special_upload_uploaded_handling(attribute_name, file) if !self.obj.binary? # standard handling! self.obj.set(attribute_name.to_s, self.upload_uploaded_file(file)) else ext = ::File.extname(file.original_filename).to_s[1..-1] self.obj.upload(file.open, ext) end end def upload_file(file) upload = Fiona7::Builder::IndirectBlobBuilder.new(self.obj, ::File.basename(file.path), file).call encoded_id = Fiona7::BlobIdGenerator.new(upload.id, upload.last_changed).call {title: encoded_id, destination_object: upload} end def upload_uploaded_file(file) upload = Fiona7::Builder::IndirectBlobBuilder.new(self.obj, file.original_filename, file.open).call encoded_id = Fiona7::BlobIdGenerator.new(upload.id, upload.last_changed).call {title: encoded_id, destination_object: upload} end end end end