Shrine 2.14.0
New features
Shrine::Storage::S3now accepts a:clientoption for specifying an AWS SDK client object. This allows the user to configure client-side encryption by passing aAws::S3::Encryption::Clientobject:client = Aws::S3::Encryption::Client.new( kms_key_id: "alias/my-key", **options ) Shrine::Storage::S3.new(client: client, bucket: "my-bucket")The metadata blocks in the
add_metadataplugin now have previous metadata available to them incontext[:metadata](thanks to @jrochkind).add_metadata :foo do |io, context| context[:metadata] #=> # { # "filename" => "nature.jpg", # "size" => 123, # "mime_type" => "image/jpeg" # } "foo" end add_metadata :bar do |io, context| context[:metadata] #=> # { # "filename" => "nature.jpg", # "size" => 123, # "mime_type" => "image/jpeg", # "foo" => "foo" # } "bar" endUploadedFile#to_rack_responsefromrack_responseplugin now accepts:typeand:filenameoptions for overriding the values in metadata that would otherwise be used for theContent-TypeandContent-Dispositionresponse headers.status, headers, body = uploaded_file.to_rack_response( type: "text/csv; charset=utf-8", filename: "export.csv", ) headers["Content-Type"] #=> "text/csv; charset=utf-8" headers["Content-Disposition"] #=> "inline; filename=\"export.csv\""Shrine.data_urifromdata_uriplugin now accepts a:filenamestring, which will be returned inShrine::Plugins::DataUri::DataFile#original_filename.io = Shrine.data_uri("data:,content", filename: "foo.txt") io.original_filename #=> "foo.txt"UploadedFile#download_urlfromdownload_endpointplugin now accepts a:hostoption. Previously it was only possible to configure the URL host on the plugin level.uploaded_file.download_url(host: "https://example.com")Attacher#cached?andAttacher#stored?now accept an optional uploaded file parameter, and return whether the given uploaded file is uploaded to the temporary or permanent storage of the attacher (thanks to @jrochkind).
Performance improvements
UploadedFile#downloaddoesn't callStorage#downloadanymore (onlyStorage#open). This improves performance when the uploaded file is already opened, e.g. when usingrefresh_metadataplugin andShrine.with_fileduring metadata extraction. Instead of performing a new download request,UploadedFile#downloadwill in this case reuse the already opened IO object.Added
tempfileplugin that makes it easier to avoid copying theUploadedFileto disk multiple times during promotion. For example, in the following code the uploaded file will be downloaded to disk only once instead of three times.Shrine.plugin :tempfileclass MyUploader < Shrine plugin :processing plugin :add_metadata plugin :refresh_metadata process(:store) do |io, context| io.open do io.refresh_metadata! processor = ImageProcessing::Vips.source(io.tempfile) # ... processing ... end end add_metadata :foo do |io, context| Shrine.with_file(io) { "..." } unless context[:action] == :store end add_metadata :bar do |io, context| Shrine.with_file(io) { "..." } unless context[:action] == :store end endUploadedFile#refresh_metadata!fromrefresh_metadataplugin now detects when the uploaded file is already opened and in that case doesn't re-open the file. This makes code like this faster:uploaded_file.open do uploaded_file.refresh_metadata! # doesn't re-open the file anymore endThe
rack_responseplugin now integrates withRack::Sendfilemiddleware whenShrine::Storage::FileSystemis used. It does so by making the response body respond to#to_path.#<name>_attacherdoesn't look up the attachment class every time it's called with a new model instance anymore, making it slightly faster (thanks to @printercu).
Other improvements
The
lib/shrine.rbfile has been split intolib/shrine.rb,lib/shrine/uploaded_file.rb,lib/shrine/attacher.rb,lib/shrine/attachment.rb, andlib/shrine/plugins.rb(thanks to @printercu).Shrine::Storage::S3andrack_responseplugin now use the content_disposition gem for generating correctly formattedContent-Dispositionheader values.The
S3#downloadandS3#openmethods now work correctly with server-side encryption (as long as the necessary:sse_*parameters are passed in).Fixed
FileSystem#clear!not working with symlinks (at least on MRI).Fixed
add_metadataplugin overriding previously defined metadata blocks when loaded again.Fixed
processingplugin overriding previously defined processing blocks when loaded again.Fixed
backgroundingplugin erroring when temorary/permanent storage is declared inShrine::Attachment.newand there are no:cacheor:storestorages defined.Fixed
UploadedFile#extension(and thus the tempfile inUploadedFile#download) including URL query parameters in the file extension whenShrine::Storage::Urlis used (shrine-urlgem) with URLs that have query parameters (thanks to @jrochkind).Fixed
backgroundingplugin aborting promotion when cached file metadata was refreshed in the processing block and Active Record JSON column was used.refresh_metadataplugin now avoids mutating the uploaded file data hashbackgroundingplugin now continues promotion if cached file metadata has changed
The
Shrine.data_urimethod from thedata_uriplugin now picks up media type parameters from the data URI and includes them inShrine::Plugins::DataUri::DataFile#content_type.io = Shrine.data_uri("data:text/plain;charset=utf-8,content") io.content_type #=> # BEFORE: "text/plain" # AFTER: "text/plain;charset=utf-8"When fetching
mime_typemetadata value fromio.content_type, any media type parameters are now stripped. This means that if the user uploads a text file with aContent-Typeoftext/plain; charset=utf-8, themime_typewill now correctly be stored astext/plain. This fixes any MIME type validations that might not have been passing due to additional media type parameters.When
determine_mime_typeplugin is loaded with the:defaultanalyzer, a warning is not printed anymore.When
Shrine::Storage::S3is initialized withbucket: nil, an appropriate error message is now raised.The
:content_typeMIME type analyzer has been added to theShrine.mime_type_analyzershash indetermine_mime_typeplugin (previously known as:default).
Documentation
- The Retrieving Uploads guide has been added.
Backwards compatibility
Support for MRI 2.1 and MRI 2.2 has been dropped.
Shrine::Plugins::Basemodule has been removed and contained modules have been moved toInstanceMethodsandClassMethodsmodules inside the corresponding core classes. This should not break anything unless you were referencing those modules directly.Shrine::Plugins::Base::InstanceMethods => Shrine::InstanceMethods Shrine::Plugins::Base::ClassMethods => Shrine::ClassMethods Shrine::Plugins::Base::FileMethods => Shrine::UploadedFile::InstanceMethods Shrine::Plugins::Base::FileClassMethods => Shrine::UploadedFile::ClassMethods Shrine::Plugins::Base::AttacherMethods => Shrine::Attacher::InstanceMethods Shrine::Plugins::Base::AttacherClassMethods => Shrine::Attacher::ClassMethods Shrine::Plugins::Base::AttachmentMethods => Shrine::Attachment::InstanceMethods Shrine::Plugins::Base::AttachmentClassMethods => Shrine::Attachment::ClassMethodsUploadedFile#downloaddoesn't callStorage#downloadanymore, it now always callsStorage#open. SinceStorage#downloadis not used anywhere else in Shrine, storages can remove the#downloadmethod.Shrine::Storage::S3#downloadhas been deprecated and will be removed in Shrine 3.In
Shrine::Storage::S3#upload,#open, and#presignit's now deprecated to pass theContent-Dispositionheader value with non-ASCII characters. Starting with Shrine 3 these characters won't be escaped anymore. You should now use the content_disposition gem to properly format theContent-Dispositionheader value.# BAD: plugin :default_url_options, store: -> (io, **options) do { response_content_disposition: "attachment; filename=\"#{io.original_filename}\"" } end # GOOD: plugin :default_url_options, store: -> (io, **options) do { response_content_disposition: ContentDisposition.attachment(io.original_filename) } endThe
mime_typemetadata value will now strip any additional media type parameters such ascharsetfromio.content_type. If you were relying on this behaviour, you will need to update your code.In
determine_mime_typeplugin, the:defaultMIME type analyzer has been renamed to:content_type. The:defaultalias will stop being supported in Shrine 3.plugin :determine_mime_type, analyzer: :default # should be changed to plugin :determine_mime_type, analyzer: :content_typeThe
UploadedFileprivate methods that were added by therack_responseplugin have now been moved to an internal class (leaving only#to_rack_response). If you've are currently overriding any of these private methods, you'll need to update your code.The
UploadedFileprivate methods that were added by thedownload_endpointplugin have now been moved to an internal class (leaving only#download_url). If you've are currently overriding any of these private methods, you'll need to update your code.