shrine 3.0.0.beta2 → 3.0.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +45 -1
 - data/README.md +100 -106
 - data/doc/advantages.md +90 -88
 - data/doc/attacher.md +322 -152
 - data/doc/carrierwave.md +105 -113
 - data/doc/changing_derivatives.md +308 -0
 - data/doc/changing_location.md +92 -21
 - data/doc/changing_storage.md +107 -0
 - data/doc/creating_plugins.md +1 -1
 - data/doc/design.md +8 -9
 - data/doc/direct_s3.md +3 -2
 - data/doc/metadata.md +97 -78
 - data/doc/multiple_files.md +3 -3
 - data/doc/paperclip.md +89 -88
 - data/doc/plugins/activerecord.md +3 -12
 - data/doc/plugins/backgrounding.md +126 -100
 - data/doc/plugins/derivation_endpoint.md +4 -5
 - data/doc/plugins/derivatives.md +63 -32
 - data/doc/plugins/download_endpoint.md +54 -1
 - data/doc/plugins/entity.md +1 -0
 - data/doc/plugins/form_assign.md +53 -0
 - data/doc/plugins/mirroring.md +37 -16
 - data/doc/plugins/multi_cache.md +22 -0
 - data/doc/plugins/presign_endpoint.md +1 -1
 - data/doc/plugins/remote_url.md +19 -4
 - data/doc/plugins/validation.md +83 -0
 - data/doc/processing.md +149 -133
 - data/doc/refile.md +68 -63
 - data/doc/release_notes/3.0.0.md +835 -0
 - data/doc/securing_uploads.md +56 -36
 - data/doc/storage/s3.md +2 -2
 - data/doc/testing.md +104 -120
 - data/doc/upgrading_to_3.md +538 -0
 - data/doc/validation.md +48 -87
 - data/lib/shrine.rb +7 -4
 - data/lib/shrine/attacher.rb +16 -6
 - data/lib/shrine/plugins/activerecord.rb +33 -14
 - data/lib/shrine/plugins/atomic_helpers.rb +1 -1
 - data/lib/shrine/plugins/backgrounding.rb +23 -89
 - data/lib/shrine/plugins/data_uri.rb +13 -2
 - data/lib/shrine/plugins/derivation_endpoint.rb +7 -11
 - data/lib/shrine/plugins/derivatives.rb +44 -20
 - data/lib/shrine/plugins/download_endpoint.rb +26 -0
 - data/lib/shrine/plugins/form_assign.rb +6 -3
 - data/lib/shrine/plugins/keep_files.rb +2 -2
 - data/lib/shrine/plugins/mirroring.rb +62 -22
 - data/lib/shrine/plugins/model.rb +2 -2
 - data/lib/shrine/plugins/multi_cache.rb +27 -0
 - data/lib/shrine/plugins/remote_url.rb +25 -10
 - data/lib/shrine/plugins/remove_invalid.rb +1 -1
 - data/lib/shrine/plugins/sequel.rb +39 -20
 - data/lib/shrine/plugins/validation.rb +3 -0
 - data/lib/shrine/storage/s3.rb +16 -1
 - data/lib/shrine/uploaded_file.rb +1 -0
 - data/lib/shrine/version.rb +1 -1
 - data/shrine.gemspec +1 -1
 - metadata +12 -7
 - data/doc/migrating_storage.md +0 -76
 - data/doc/regenerating_versions.md +0 -143
 - data/lib/shrine/plugins/attacher_options.rb +0 -55
 
| 
         @@ -58,7 +58,7 @@ apply to an attached file. For example, we can generate image thumbnails using 
     | 
|
| 
       58 
58 
     | 
    
         
             
            the [ImageProcessing] gem:
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
            ```rb
         
     | 
| 
       61 
     | 
    
         
            -
            gem "image_processing", "~> 1. 
     | 
| 
      
 61 
     | 
    
         
            +
            gem "image_processing", "~> 1.8"
         
     | 
| 
       62 
62 
     | 
    
         
             
            ```
         
     | 
| 
       63 
63 
     | 
    
         
             
            ```rb
         
     | 
| 
       64 
64 
     | 
    
         
             
            require "image_processing/mini_magick"
         
     | 
| 
         @@ -117,13 +117,12 @@ derivation :thumbnail do |file, arg1, arg2, ...| 
     | 
|
| 
       117 
117 
     | 
    
         | 
| 
       118 
118 
     | 
    
         
             
              # ... do processing ...
         
     | 
| 
       119 
119 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
              # return result as a File 
     | 
| 
      
 120 
     | 
    
         
            +
              # return result as a File or Tempfile object
         
     | 
| 
       121 
121 
     | 
    
         
             
            end
         
     | 
| 
       122 
122 
     | 
    
         
             
            ```
         
     | 
| 
       123 
123 
     | 
    
         | 
| 
       124 
     | 
    
         
            -
            The derivation block is expected to return the processed file  
     | 
| 
       125 
     | 
    
         
            -
            ` 
     | 
| 
       126 
     | 
    
         
            -
            then rendered in the HTTP response.
         
     | 
| 
      
 124 
     | 
    
         
            +
            The derivation block is expected to return the processed file as a `File` or
         
     | 
| 
      
 125 
     | 
    
         
            +
            `Tempfile` object. The resulting file is then rendered in the HTTP response.
         
     | 
| 
       127 
126 
     | 
    
         | 
| 
       128 
127 
     | 
    
         
             
            ### Performance
         
     | 
| 
       129 
128 
     | 
    
         | 
    
        data/doc/plugins/derivatives.md
    CHANGED
    
    | 
         @@ -5,13 +5,14 @@ the main attached file. The processed file data will be saved together with the 
     | 
|
| 
       5 
5 
     | 
    
         
             
            main attachment data in the same record attribute.
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ```rb
         
     | 
| 
       8 
     | 
    
         
            -
            plugin :derivatives
         
     | 
| 
      
 8 
     | 
    
         
            +
            Shrine.plugin :derivatives
         
     | 
| 
       9 
9 
     | 
    
         
             
            ```
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            ## Contents
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            * [API overview](#api-overview)
         
     | 
| 
       14 
14 
     | 
    
         
             
            * [Creating derivatives](#creating-derivatives)
         
     | 
| 
      
 15 
     | 
    
         
            +
              - [Naming processors](#naming-processors)
         
     | 
| 
       15 
16 
     | 
    
         
             
              - [Derivatives storage](#derivatives-storage)
         
     | 
| 
       16 
17 
     | 
    
         
             
              - [Nesting derivatives](#nesting-derivatives)
         
     | 
| 
       17 
18 
     | 
    
         
             
            * [Retrieving derivatives](#retrieving-derivatives)
         
     | 
| 
         @@ -57,21 +58,19 @@ Here is an example of generating image thumbnails: 
     | 
|
| 
       57 
58 
     | 
    
         | 
| 
       58 
59 
     | 
    
         
             
            ```rb
         
     | 
| 
       59 
60 
     | 
    
         
             
            # Gemfile
         
     | 
| 
       60 
     | 
    
         
            -
            gem "image_processing", "~> 1. 
     | 
| 
      
 61 
     | 
    
         
            +
            gem "image_processing", "~> 1.8"
         
     | 
| 
       61 
62 
     | 
    
         
             
            ```
         
     | 
| 
       62 
63 
     | 
    
         
             
            ```rb
         
     | 
| 
       63 
64 
     | 
    
         
             
            require "image_processing/mini_magick"
         
     | 
| 
       64 
65 
     | 
    
         | 
| 
       65 
66 
     | 
    
         
             
            class ImageUploader < Shrine
         
     | 
| 
       66 
     | 
    
         
            -
               
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
              Attacher.derivatives_processor :thumbnails do |original|
         
     | 
| 
       69 
     | 
    
         
            -
                processor = ImageProcessing::MiniMagick.source(original)
         
     | 
| 
      
 67 
     | 
    
         
            +
              Attacher.derivatives_processor do |original|
         
     | 
| 
      
 68 
     | 
    
         
            +
                magick = ImageProcessing::MiniMagick.source(original)
         
     | 
| 
       70 
69 
     | 
    
         | 
| 
       71 
70 
     | 
    
         
             
                {
         
     | 
| 
       72 
     | 
    
         
            -
                  small:   
     | 
| 
       73 
     | 
    
         
            -
                  medium:  
     | 
| 
       74 
     | 
    
         
            -
                  large:   
     | 
| 
      
 71 
     | 
    
         
            +
                  small:  magick.resize_to_limit!(300, 300),
         
     | 
| 
      
 72 
     | 
    
         
            +
                  medium: magick.resize_to_limit!(500, 500),
         
     | 
| 
      
 73 
     | 
    
         
            +
                  large:  magick.resize_to_limit!(800, 800),
         
     | 
| 
       75 
74 
     | 
    
         
             
                }
         
     | 
| 
       76 
75 
     | 
    
         
             
              end
         
     | 
| 
       77 
76 
     | 
    
         
             
            end
         
     | 
| 
         @@ -82,20 +81,20 @@ class Photo < Model(:image_data) 
     | 
|
| 
       82 
81 
     | 
    
         
             
            end
         
     | 
| 
       83 
82 
     | 
    
         
             
            ```
         
     | 
| 
       84 
83 
     | 
    
         
             
            ```rb
         
     | 
| 
       85 
     | 
    
         
            -
            photo 
     | 
| 
       86 
     | 
    
         
            -
            photo.image_derivatives  
     | 
| 
      
 84 
     | 
    
         
            +
            photo = Photo.new(image: file)
         
     | 
| 
      
 85 
     | 
    
         
            +
            photo.image_derivatives! # calls derivatives processor and uploads results
         
     | 
| 
      
 86 
     | 
    
         
            +
            photo.save
         
     | 
| 
      
 87 
     | 
    
         
            +
            ```
         
     | 
| 
       87 
88 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
            #   large:  #<Shrine::UploadedFile @id="large.jpg" @storage_key=:store ...>,
         
     | 
| 
       94 
     | 
    
         
            -
            # }
         
     | 
| 
      
 89 
     | 
    
         
            +
            If you're allowing the attached file to be updated later on, in your update
         
     | 
| 
      
 90 
     | 
    
         
            +
            route make sure to create derivatives for new attachments:
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            photo.image_derivatives! if photo.image_changed?
         
     | 
| 
       95 
94 
     | 
    
         
             
            ```
         
     | 
| 
       96 
95 
     | 
    
         | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
            the main file data:
         
     | 
| 
      
 96 
     | 
    
         
            +
            Once derivatives have been created, their data is stored in the `#<name>_data`
         
     | 
| 
      
 97 
     | 
    
         
            +
            record attribute alongside the main file data:
         
     | 
| 
       99 
98 
     | 
    
         | 
| 
       100 
99 
     | 
    
         
             
            ```rb
         
     | 
| 
       101 
100 
     | 
    
         
             
            photo.image_data #=>
         
     | 
| 
         @@ -111,16 +110,23 @@ photo.image_data #=> 
     | 
|
| 
       111 
110 
     | 
    
         
             
            # }
         
     | 
| 
       112 
111 
     | 
    
         
             
            ```
         
     | 
| 
       113 
112 
     | 
    
         | 
| 
      
 113 
     | 
    
         
            +
            You can then retrieve derivatives as follows:
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 116 
     | 
    
         
            +
            photo.image(:large)           #=> #<Shrine::UploadedFile>
         
     | 
| 
      
 117 
     | 
    
         
            +
            photo.image(:large).url       #=> "https://s3.amazonaws.com/path/to/large.jpg"
         
     | 
| 
      
 118 
     | 
    
         
            +
            photo.image(:large).size      #=> 43843
         
     | 
| 
      
 119 
     | 
    
         
            +
            photo.image(:large).mime_type #=> "image/jpeg"
         
     | 
| 
      
 120 
     | 
    
         
            +
            ```
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
       114 
122 
     | 
    
         
             
            The `#<name>_derivatives!` model method delegates to
         
     | 
| 
       115 
123 
     | 
    
         
             
            `Attacher#create_derivatives`, which you can use if you're using
         
     | 
| 
       116 
124 
     | 
    
         
             
            `Shrine::Attacher` directly:
         
     | 
| 
       117 
125 
     | 
    
         | 
| 
       118 
126 
     | 
    
         
             
            ```rb
         
     | 
| 
       119 
     | 
    
         
            -
            attacher.file 
     | 
| 
       120 
     | 
    
         
            -
            attacher. 
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
            attacher.create_derivatives(:thumbnails) # calls registered processor and uploads results
         
     | 
| 
       123 
     | 
    
         
            -
            attacher.derivatives #=>
         
     | 
| 
      
 127 
     | 
    
         
            +
            attacher.file               #=> #<Shrine::UploadedFile @id="original.jpg" @storage_key=:store ...>
         
     | 
| 
      
 128 
     | 
    
         
            +
            attacher.create_derivatives # calls registered processor and uploads results
         
     | 
| 
      
 129 
     | 
    
         
            +
            attacher.derivatives        #=>
         
     | 
| 
       124 
130 
     | 
    
         
             
            # {
         
     | 
| 
       125 
131 
     | 
    
         
             
            #   small:  #<Shrine::UploadedFile @id="small.jpg" @storage_key=:store ...>,
         
     | 
| 
       126 
132 
     | 
    
         
             
            #   medium: #<Shrine::UploadedFile @id="medium.jpg" @storage_key=:store ...>,
         
     | 
| 
         @@ -130,14 +136,39 @@ attacher.derivatives #=> 
     | 
|
| 
       130 
136 
     | 
    
         | 
| 
       131 
137 
     | 
    
         
             
            By default, the `Attacher#create_derivatives` method downloads the attached
         
     | 
| 
       132 
138 
     | 
    
         
             
            file, calls the processor, uploads results to attacher's permanent storage, and
         
     | 
| 
       133 
     | 
    
         
            -
            saves uploaded files on the attacher.
         
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
            Any additional arguments are forwarded to
         
     | 
| 
      
 139 
     | 
    
         
            +
            saves uploaded files on the attacher. Any additional arguments are forwarded to
         
     | 
| 
       136 
140 
     | 
    
         
             
            [`Attacher#process_derivatives`](#processing-derivatives):
         
     | 
| 
       137 
141 
     | 
    
         | 
| 
       138 
142 
     | 
    
         
             
            ```rb
         
     | 
| 
       139 
     | 
    
         
            -
            attacher.create_derivatives( 
     | 
| 
       140 
     | 
    
         
            -
            attacher.create_derivatives( 
     | 
| 
      
 143 
     | 
    
         
            +
            attacher.create_derivatives(different_source) # pass a different source file
         
     | 
| 
      
 144 
     | 
    
         
            +
            attacher.create_derivatives(foo: "bar")       # pass custom options to the processor
         
     | 
| 
      
 145 
     | 
    
         
            +
            ```
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            ### Naming processors
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            If you want to have multiple processors for an uploader, you can assign each
         
     | 
| 
      
 150 
     | 
    
         
            +
            processor a name. Then when creating derivatives you can specify the name of
         
     | 
| 
      
 151 
     | 
    
         
            +
            the desired processor.
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 154 
     | 
    
         
            +
            class ImageUploader < Shrine
         
     | 
| 
      
 155 
     | 
    
         
            +
              Attacher.derivatives_processor :thumbnails do |original|
         
     | 
| 
      
 156 
     | 
    
         
            +
                # ...
         
     | 
| 
      
 157 
     | 
    
         
            +
              end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
              Attacher.derivatives_processor :crop do |original|
         
     | 
| 
      
 160 
     | 
    
         
            +
                # ...
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 164 
     | 
    
         
            +
            end
         
     | 
| 
      
 165 
     | 
    
         
            +
            ```
         
     | 
| 
      
 166 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 167 
     | 
    
         
            +
            # ...
         
     | 
| 
      
 168 
     | 
    
         
            +
            photo.image_derivatives!(:thumbnails)
         
     | 
| 
      
 169 
     | 
    
         
            +
            # or
         
     | 
| 
      
 170 
     | 
    
         
            +
            attacher.create_derivatives(:thumbnails)
         
     | 
| 
      
 171 
     | 
    
         
            +
            # ...
         
     | 
| 
       141 
172 
     | 
    
         
             
            ```
         
     | 
| 
       142 
173 
     | 
    
         | 
| 
       143 
174 
     | 
    
         
             
            ### Derivatives storage
         
     | 
| 
         @@ -244,7 +275,7 @@ photo.image_derivatives #=> { thumbnail: { small: ..., medium: ..., large: ... } 
     | 
|
| 
       244 
275 
     | 
    
         | 
| 
       245 
276 
     | 
    
         
             
            photo.image_derivatives.dig(:thumbnail, :small) #=> #<Shrine::UploadedFile>
         
     | 
| 
       246 
277 
     | 
    
         
             
            photo.image_derivatives(:thumbnail, :small)     #=> #<Shrine::UploadedFile>
         
     | 
| 
       247 
     | 
    
         
            -
            photo.image(:thumbnails :small) 
     | 
| 
      
 278 
     | 
    
         
            +
            photo.image(:thumbnails, :small)                #=> #<Shrine::UploadedFile>
         
     | 
| 
       248 
279 
     | 
    
         
             
            ```
         
     | 
| 
       249 
280 
     | 
    
         | 
| 
       250 
281 
     | 
    
         
             
            When using `Shrine::Attacher` directly, you can retrieve derivatives using
         
     | 
| 
         @@ -288,7 +319,7 @@ You can use the [`default_url`][default_url] plugin to set up URL fallbacks: 
     | 
|
| 
       288 
319 
     | 
    
         | 
| 
       289 
320 
     | 
    
         
             
            ```rb
         
     | 
| 
       290 
321 
     | 
    
         
             
            Attacher.default_url do |derivative: nil, **|
         
     | 
| 
       291 
     | 
    
         
            -
              "https:// 
     | 
| 
      
 322 
     | 
    
         
            +
              "https://my-app.com/fallbacks/#{derivative}.jpg" if derivative
         
     | 
| 
       292 
323 
     | 
    
         
             
            end
         
     | 
| 
       293 
324 
     | 
    
         
             
            ```
         
     | 
| 
       294 
325 
     | 
    
         
             
            ```rb
         
     | 
| 
         @@ -5,11 +5,13 @@ downloading uploaded files from specified storages. This can be useful when 
     | 
|
| 
       5 
5 
     | 
    
         
             
            files from your storage isn't accessible over URL (e.g. database storages) or
         
     | 
| 
       6 
6 
     | 
    
         
             
            if you want to authenticate your downloads.
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
            ## Global Endpoint 
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       8 
10 
     | 
    
         
             
            You can configure the plugin with the path prefix which the endpoint will be
         
     | 
| 
       9 
11 
     | 
    
         
             
            mounted on.
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
            ```rb
         
     | 
| 
       12 
     | 
    
         
            -
            plugin :download_endpoint, prefix: "attachments"
         
     | 
| 
      
 14 
     | 
    
         
            +
            Shrine.plugin :download_endpoint, prefix: "attachments"
         
     | 
| 
       13 
15 
     | 
    
         
             
            ```
         
     | 
| 
       14 
16 
     | 
    
         | 
| 
       15 
17 
     | 
    
         
             
            The plugin adds a `Shrine.download_endpoint` method which returns a Rack
         
     | 
| 
         @@ -30,6 +32,57 @@ Links to the download endpoint are generated by calling 
     | 
|
| 
       30 
32 
     | 
    
         
             
            ```rb
         
     | 
| 
       31 
33 
     | 
    
         
             
            uploaded_file.download_url #=> "/attachments/eyJpZCI6ImFkdzlyeTM..."
         
     | 
| 
       32 
34 
     | 
    
         
             
            ```
         
     | 
| 
      
 35 
     | 
    
         
            +
            ## Endpoint via Uploader
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            You can also configure the plugin in the uploader directly - just make sure to mount it via your Uploader-class.
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 40 
     | 
    
         
            +
            class ImageUploader  < Shrine
         
     | 
| 
      
 41 
     | 
    
         
            +
              plugin :download_endpoint, prefix: "images"
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
            ```
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 46 
     | 
    
         
            +
            # config/routes.rb (Rails)
         
     | 
| 
      
 47 
     | 
    
         
            +
            Rails.application.routes.draw do
         
     | 
| 
      
 48 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 49 
     | 
    
         
            +
              mount ImageUploader.download_endpoint => "/images"
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
            ```
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            *Hint: For shrine versions 2.x -> ensure that you don't include the plugin twice (globally and in your uploader class - see #408)*
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            ## Calling from a controller
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            If you want to run additional code around the download (such as authentication),
         
     | 
| 
      
 58 
     | 
    
         
            +
            mounting the download endpoint in your router might be limiting. You can instead
         
     | 
| 
      
 59 
     | 
    
         
            +
            create a custom controller action and handle download requests there using
         
     | 
| 
      
 60 
     | 
    
         
            +
            `Shrine.download_response`:
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 63 
     | 
    
         
            +
            # config/routes.rb (Rails)
         
     | 
| 
      
 64 
     | 
    
         
            +
            Rails.application.routes.draw do
         
     | 
| 
      
 65 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 66 
     | 
    
         
            +
              get "/attachments/*rest", to: "downloads#image"
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
      
 68 
     | 
    
         
            +
            ```
         
     | 
| 
      
 69 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 70 
     | 
    
         
            +
            # app/controllers/downloads_controller.rb (Rails)
         
     | 
| 
      
 71 
     | 
    
         
            +
            class DownloadsController < ApplicationController
         
     | 
| 
      
 72 
     | 
    
         
            +
              def image
         
     | 
| 
      
 73 
     | 
    
         
            +
                # ... we can perform authentication here ...
         
     | 
| 
      
 74 
     | 
    
         
            +
                set_rack_response ImageUploader.download_response(request.env)
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              private
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              def set_rack_response((status, headers, body))
         
     | 
| 
      
 80 
     | 
    
         
            +
                self.status = status
         
     | 
| 
      
 81 
     | 
    
         
            +
                self.headers.merge!(headers)
         
     | 
| 
      
 82 
     | 
    
         
            +
                self.response_body = body
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
      
 85 
     | 
    
         
            +
            ```
         
     | 
| 
       33 
86 
     | 
    
         | 
| 
       34 
87 
     | 
    
         
             
            ## Host
         
     | 
| 
       35 
88 
     | 
    
         | 
    
        data/doc/plugins/entity.md
    CHANGED
    
    | 
         @@ -248,5 +248,6 @@ By default, attachment data is serialized into JSON using the `JSON` standard 
     | 
|
| 
       248 
248 
     | 
    
         
             
            library. If you want to change how data is serialized, see the
         
     | 
| 
       249 
249 
     | 
    
         
             
            [`column`][column serializer] plugin docs.
         
     | 
| 
       250 
250 
     | 
    
         | 
| 
      
 251 
     | 
    
         
            +
            [column]: /doc/plugins/column.md#readme
         
     | 
| 
       251 
252 
     | 
    
         
             
            [entity]: /lib/shrine/plugins/entity.rb
         
     | 
| 
       252 
253 
     | 
    
         
             
            [column serializer]: /doc/plugins/column.md#serializer
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Form Assign
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            The [`form_assign`][form_assign] plugin allows attaching file from form params
         
     | 
| 
      
 4 
     | 
    
         
            +
            without a form object.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 7 
     | 
    
         
            +
            plugin :form_assign
         
     | 
| 
      
 8 
     | 
    
         
            +
            ```
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            The `Attacher#form_assign` method will detect the file param and assign it to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the attacher:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 14 
     | 
    
         
            +
            attacher = photo.image_attacher
         
     | 
| 
      
 15 
     | 
    
         
            +
            attacher.form_assign("image" => file, "title" => "...", "description" => "...")
         
     | 
| 
      
 16 
     | 
    
         
            +
            attacher.file #=> #<Shrine::UploadedFile>
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            It works with `remote_url`, `data_uri`, and `remove_attachment` plugins:
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 22 
     | 
    
         
            +
            # remote_url plugin
         
     | 
| 
      
 23 
     | 
    
         
            +
            attacher.form_assign("image_remote_url" => "https://example.com/...")
         
     | 
| 
      
 24 
     | 
    
         
            +
            attacher.file #=> #<Shrine::UploadedFile>
         
     | 
| 
      
 25 
     | 
    
         
            +
            ```
         
     | 
| 
      
 26 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 27 
     | 
    
         
            +
            # data_uri plugin
         
     | 
| 
      
 28 
     | 
    
         
            +
            attacher.form_assign("image_data_uri" => "data:image/jpeg;base64,...")
         
     | 
| 
      
 29 
     | 
    
         
            +
            attacher.file #=> #<Shrine::UploadedFile>
         
     | 
| 
      
 30 
     | 
    
         
            +
            ```
         
     | 
| 
      
 31 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 32 
     | 
    
         
            +
            # remove_attachment plugin
         
     | 
| 
      
 33 
     | 
    
         
            +
            attacher.form_assign("remove_image" => "1")
         
     | 
| 
      
 34 
     | 
    
         
            +
            attacher.file #=> nil
         
     | 
| 
      
 35 
     | 
    
         
            +
            ```
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            The return value is a hash with form params, with file param replaced with
         
     | 
| 
      
 38 
     | 
    
         
            +
            cached file data, which can later be assigned again to the record.
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 41 
     | 
    
         
            +
            attacher.form_assign("image" => file, "title" => "...", "description" => "...")
         
     | 
| 
      
 42 
     | 
    
         
            +
            #=> { :image => '{"id":"...","storage":"...","metadata":"..."}', "title" => "...", "description" => "..." }
         
     | 
| 
      
 43 
     | 
    
         
            +
            ```
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            You can also have attached file data returned as the `<name>_data` attribute,
         
     | 
| 
      
 46 
     | 
    
         
            +
            suitable for persisting.
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 49 
     | 
    
         
            +
            attacher.form_assign({ "image" => image, ... }, result: :attributes)
         
     | 
| 
      
 50 
     | 
    
         
            +
            #=> { :image_data => '{"id":"...","storage":"...","metadata":"..."}', "title" => "...", "description" => "..." }
         
     | 
| 
      
 51 
     | 
    
         
            +
            ```
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            [form_assign]: /lib/shrine/plugins/form_assign.rb
         
     | 
    
        data/doc/plugins/mirroring.md
    CHANGED
    
    | 
         @@ -12,8 +12,16 @@ With the above setup, any upload and delete to `:store` will be replicated to 
     | 
|
| 
       12 
12 
     | 
    
         
             
            `:other_store`.
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            ```rb
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
            file = Shrine.upload(io, :store) # uploads to :store and :other_store
         
     | 
| 
      
 16 
     | 
    
         
            +
            file.delete                      # deletes from :store and :other_store
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            You can skip mirroring for a specific upload/delete call by passing `mirror:
         
     | 
| 
      
 20 
     | 
    
         
            +
            false`:
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 23 
     | 
    
         
            +
            file = Shrine.upload(io, :store, mirror: false) # skips mirroring
         
     | 
| 
      
 24 
     | 
    
         
            +
            file.delete(mirror: false)                      # skips mirroring
         
     | 
| 
       17 
25 
     | 
    
         
             
            ```
         
     | 
| 
       18 
26 
     | 
    
         | 
| 
       19 
27 
     | 
    
         
             
            ## Multiple storages
         
     | 
| 
         @@ -40,42 +48,43 @@ Shrine.plugin :mirroring, mirror: { ... }, delete: false 
     | 
|
| 
       40 
48 
     | 
    
         
             
            You can have mirroring performed in a background job:
         
     | 
| 
       41 
49 
     | 
    
         | 
| 
       42 
50 
     | 
    
         
             
            ```rb
         
     | 
| 
       43 
     | 
    
         
            -
            Shrine. 
     | 
| 
       44 
     | 
    
         
            -
              MirrorUploadJob. 
     | 
| 
      
 51 
     | 
    
         
            +
            Shrine.mirror_upload_block do |file|
         
     | 
| 
      
 52 
     | 
    
         
            +
              MirrorUploadJob.perform_later(file.shrine_class, file.data)
         
     | 
| 
       45 
53 
     | 
    
         
             
            end
         
     | 
| 
       46 
54 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
            Shrine. 
     | 
| 
       48 
     | 
    
         
            -
              MirrorDeleteJob. 
     | 
| 
      
 55 
     | 
    
         
            +
            Shrine.mirror_delete_block do |file|
         
     | 
| 
      
 56 
     | 
    
         
            +
              MirrorDeleteJob.perform_later(file.shrine_class, file.data)
         
     | 
| 
       49 
57 
     | 
    
         
             
            end
         
     | 
| 
       50 
58 
     | 
    
         
             
            ```
         
     | 
| 
       51 
59 
     | 
    
         
             
            ```rb
         
     | 
| 
       52 
     | 
    
         
            -
            class MirrorUploadJob
         
     | 
| 
       53 
     | 
    
         
            -
              include Sidekiq::Worker
         
     | 
| 
      
 60 
     | 
    
         
            +
            class MirrorUploadJob < ActiveJob::Base
         
     | 
| 
       54 
61 
     | 
    
         
             
              def perform(shrine_class, file_data)
         
     | 
| 
       55 
     | 
    
         
            -
                 
     | 
| 
       56 
     | 
    
         
            -
                 
     | 
| 
      
 62 
     | 
    
         
            +
                file = shrine_class.uploaded_file(file_data)
         
     | 
| 
      
 63 
     | 
    
         
            +
                file.mirror_upload
         
     | 
| 
       57 
64 
     | 
    
         
             
              end
         
     | 
| 
       58 
65 
     | 
    
         
             
            end
         
     | 
| 
       59 
66 
     | 
    
         
             
            ```
         
     | 
| 
       60 
67 
     | 
    
         
             
            ```rb
         
     | 
| 
       61 
     | 
    
         
            -
            class MirrorDeleteJob
         
     | 
| 
       62 
     | 
    
         
            -
              include Sidekiq::Worker
         
     | 
| 
      
 68 
     | 
    
         
            +
            class MirrorDeleteJob < ActiveJob::Base
         
     | 
| 
       63 
69 
     | 
    
         
             
              def perform(shrine_class, file_data)
         
     | 
| 
       64 
     | 
    
         
            -
                 
     | 
| 
       65 
     | 
    
         
            -
                 
     | 
| 
      
 70 
     | 
    
         
            +
                file = shrine_class.uploaded_file(file_data)
         
     | 
| 
      
 71 
     | 
    
         
            +
                file.mirror_delete
         
     | 
| 
       66 
72 
     | 
    
         
             
              end
         
     | 
| 
       67 
73 
     | 
    
         
             
            end
         
     | 
| 
       68 
74 
     | 
    
         
             
            ```
         
     | 
| 
       69 
75 
     | 
    
         | 
| 
       70 
76 
     | 
    
         
             
            ## API
         
     | 
| 
       71 
77 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
            You can  
     | 
| 
       73 
     | 
    
         
            -
            `UploadedFile#mirror_delete`:
         
     | 
| 
      
 78 
     | 
    
         
            +
            You can disable automatic mirroring and perform mirroring manually:
         
     | 
| 
       74 
79 
     | 
    
         | 
| 
       75 
80 
     | 
    
         
             
            ```rb
         
     | 
| 
       76 
81 
     | 
    
         
             
            # disable automatic mirroring of uploads and deletes
         
     | 
| 
       77 
82 
     | 
    
         
             
            Shrine.plugin :mirroring, mirror: { ... }, upload: false, delete: false
         
     | 
| 
       78 
83 
     | 
    
         
             
            ```
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            To perform mirroring, you can call `UploadedFile#mirror_upload` and
         
     | 
| 
      
 86 
     | 
    
         
            +
            `UploadedFile#mirror_delete`:
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       79 
88 
     | 
    
         
             
            ```rb
         
     | 
| 
       80 
89 
     | 
    
         
             
            file = Shrine.upload(io, :store) # upload to :store
         
     | 
| 
       81 
90 
     | 
    
         
             
            file.mirror_upload               # upload to :other_store
         
     | 
| 
         @@ -84,4 +93,16 @@ file.delete                      # delete from :store 
     | 
|
| 
       84 
93 
     | 
    
         
             
            file.mirror_delete               # delete from :other_store
         
     | 
| 
       85 
94 
     | 
    
         
             
            ```
         
     | 
| 
       86 
95 
     | 
    
         | 
| 
      
 96 
     | 
    
         
            +
            If you've set up backgrounding, you can use
         
     | 
| 
      
 97 
     | 
    
         
            +
            `UploadedFile#mirror_upload_background` and
         
     | 
| 
      
 98 
     | 
    
         
            +
            `UploadedFile#mirror_delete_background` to call the background block instead:
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            file = Shrine.upload(io, :store) # upload to :store
         
     | 
| 
      
 102 
     | 
    
         
            +
            file.mirror_upload_background    # spawn mirror upload background job
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            file.delete                      # delete from :store
         
     | 
| 
      
 105 
     | 
    
         
            +
            file.mirror_delete_background    # spawn mirror delete background job
         
     | 
| 
      
 106 
     | 
    
         
            +
            ```
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
       87 
108 
     | 
    
         
             
            [mirroring]: /lib/shrine/plugins/mirroring.rb
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Multi Cache
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            The [`multi_cache`][multi_cache] plugin allows an attacher to accept files from
         
     | 
| 
      
 4 
     | 
    
         
            +
            additional temporary storages.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 7 
     | 
    
         
            +
            Shrine.storages = { cache: ..., cache_one: ..., cache_two: ..., store: ... }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Shrine.plugin :multi_cache, additional_cache: [:cache_one, :cache_two]
         
     | 
| 
      
 10 
     | 
    
         
            +
            ```
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```rb
         
     | 
| 
      
 12 
     | 
    
         
            +
            photo.image = { "id" => "...", "storage" => "cache", "metadata" => { ... } }
         
     | 
| 
      
 13 
     | 
    
         
            +
            photo.image.storage_key #=> :cache
         
     | 
| 
      
 14 
     | 
    
         
            +
            # or
         
     | 
| 
      
 15 
     | 
    
         
            +
            photo.image = { "id" => "...", "storage" => "cache_one", "metadata" => { ... } }
         
     | 
| 
      
 16 
     | 
    
         
            +
            photo.image.storage_key #=> :cache_one
         
     | 
| 
      
 17 
     | 
    
         
            +
            # or
         
     | 
| 
      
 18 
     | 
    
         
            +
            photo.image = { "id" => "...", "storage" => "cache_two", "metadata" => { ... } }
         
     | 
| 
      
 19 
     | 
    
         
            +
            photo.image.storage_key #=> :cache_two
         
     | 
| 
      
 20 
     | 
    
         
            +
            ```
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            [multi_cache]: /lib/shrine/plugins/multi_cache.rb
         
     | 
| 
         @@ -60,7 +60,7 @@ create a custom controller action and handle presign requests there using 
     | 
|
| 
       60 
60 
     | 
    
         
             
            # config/routes.rb (Rails)
         
     | 
| 
       61 
61 
     | 
    
         
             
            Rails.application.routes.draw do
         
     | 
| 
       62 
62 
     | 
    
         
             
              # ...
         
     | 
| 
       63 
     | 
    
         
            -
               
     | 
| 
      
 63 
     | 
    
         
            +
              get "/images/presign", to: "presigns#image"
         
     | 
| 
       64 
64 
     | 
    
         
             
            end
         
     | 
| 
       65 
65 
     | 
    
         
             
            ```
         
     | 
| 
       66 
66 
     | 
    
         
             
            ```rb
         
     |