shrine 3.0.0 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +87 -33
- data/LICENSE.txt +1 -1
- data/README.md +94 -4
- data/doc/advantages.md +35 -18
- data/doc/attacher.md +16 -17
- data/doc/carrierwave.md +75 -34
- data/doc/changing_derivatives.md +39 -39
- data/doc/design.md +134 -85
- data/doc/external/articles.md +56 -41
- data/doc/external/extensions.md +38 -34
- data/doc/getting_started.md +182 -112
- data/doc/metadata.md +79 -43
- data/doc/multiple_files.md +5 -3
- data/doc/paperclip.md +110 -42
- data/doc/plugins/activerecord.md +5 -5
- data/doc/plugins/add_metadata.md +92 -35
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +205 -169
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/entity.md +3 -3
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +2 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +21 -10
- data/doc/plugins/model.md +4 -4
- data/doc/plugins/persistence.md +1 -0
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +8 -3
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/sequel.md +4 -4
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +2 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +2 -2
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/plugins/versions.md +11 -11
- data/doc/processing.md +289 -125
- data/doc/refile.md +39 -18
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/3.0.0.md +275 -258
- data/doc/release_notes/3.0.1.md +22 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +32 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/securing_uploads.md +3 -3
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +105 -86
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +115 -33
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +8 -8
- data/lib/shrine/attacher.rb +19 -14
- data/lib/shrine/attachment.rb +5 -5
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/add_metadata.rb +12 -3
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +10 -6
- data/lib/shrine/plugins/derivatives.rb +19 -17
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/entity.rb +6 -6
- data/lib/shrine/plugins/metadata_attributes.rb +1 -1
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +2 -2
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +18 -9
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +3 -3
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/s3.rb +62 -38
- data/lib/shrine/uploaded_file.rb +5 -1
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +6 -7
- metadata +23 -29
data/doc/advantages.md
CHANGED
@@ -157,21 +157,21 @@ end
|
|
157
157
|
|
158
158
|
## Processing
|
159
159
|
|
160
|
-
Most file attachment libraries
|
161
|
-
(Paperclip, CarrierWave) or on-the-fly (Dragonfly, Refile, Active Storage).
|
160
|
+
Most file attachment libraries allow you to process files either "eagerly"
|
161
|
+
(Paperclip, CarrierWave) or "on-the-fly" (Dragonfly, Refile, Active Storage).
|
162
162
|
However, each approach is suitable for different requirements. For instance,
|
163
163
|
while on-the-fly processing is suitable for fast processing (image thumbnails,
|
164
164
|
document previews), longer running processing (video transcoding, raw images)
|
165
165
|
should be moved into a background job.
|
166
166
|
|
167
|
-
That's why Shrine supports both [
|
167
|
+
That's why Shrine supports both [eager][derivatives] and
|
168
168
|
[on-the-fly][derivation_endpoint] processing. For example, if you're handling
|
169
169
|
image uploads, you can choose to either generate a set of pre-defined
|
170
170
|
thumbnails during attachment:
|
171
171
|
|
172
172
|
```rb
|
173
173
|
class ImageUploader < Shrine
|
174
|
-
Attacher.
|
174
|
+
Attacher.derivatives do |original|
|
175
175
|
magick = ImageProcessing::MiniMagick.source(original)
|
176
176
|
|
177
177
|
{
|
@@ -261,7 +261,7 @@ gem "streamio-ffmpeg"
|
|
261
261
|
```
|
262
262
|
```rb
|
263
263
|
class VideoUploader < Shrine
|
264
|
-
Attacher.
|
264
|
+
Attacher.derivatives do |original|
|
265
265
|
transcoded = Tempfile.new ["transcoded", ".mp4"]
|
266
266
|
screenshot = Tempfile.new ["screenshot", ".jpg"]
|
267
267
|
|
@@ -276,12 +276,12 @@ end
|
|
276
276
|
```rb
|
277
277
|
movie.video_derivatives! # create derivatives
|
278
278
|
|
279
|
-
movie.video #=> #<Shrine::UploadedFile
|
280
|
-
movie.video(:transcoded) #=> #<Shrine::UploadedFile
|
281
|
-
movie.video(:screenshot) #=> #<Shrine::UploadedFile
|
279
|
+
movie.video #=> #<Shrine::UploadedFile id="5a5cd0.mov" ...>
|
280
|
+
movie.video(:transcoded) #=> #<Shrine::UploadedFile id="7481d6.mp4" ...>
|
281
|
+
movie.video(:screenshot) #=> #<Shrine::UploadedFile id="8f3136.jpg" ...>
|
282
282
|
```
|
283
283
|
|
284
|
-
## Metadata
|
284
|
+
## Metadata
|
285
285
|
|
286
286
|
Shrine automatically [extracts metadata][metadata] from each uploaded file,
|
287
287
|
including derivatives like image thumbnails, and saves them into the database
|
@@ -289,6 +289,17 @@ column. In addition to filename, filesize, and MIME type that are extracted by
|
|
289
289
|
default, you can also extract [image dimensions][store_dimensions], or your own
|
290
290
|
[custom metadata][add_metadata].
|
291
291
|
|
292
|
+
```rb
|
293
|
+
class ImageUploader < Shrine
|
294
|
+
plugin :determine_mime_type # mime_type
|
295
|
+
plugin :store_dimensions # width & height
|
296
|
+
|
297
|
+
add_metadata :resolution do |io|
|
298
|
+
image = MiniMagick::Image.new(io.path)
|
299
|
+
image.resolution
|
300
|
+
end
|
301
|
+
end
|
302
|
+
```
|
292
303
|
```rb
|
293
304
|
photo.image.metadata #=>
|
294
305
|
# {
|
@@ -297,23 +308,30 @@ photo.image.metadata #=>
|
|
297
308
|
# "mime_type" => "image/jpeg",
|
298
309
|
# "width" => 600,
|
299
310
|
# "height" => 400,
|
311
|
+
# "resolution" => [72, 72],
|
300
312
|
# ...
|
301
313
|
# }
|
302
314
|
```
|
303
315
|
|
304
|
-
|
305
|
-
|
316
|
+
## Validation
|
317
|
+
|
318
|
+
For file validations there are [built-in validators][validation_helpers], but
|
319
|
+
you can also just use plain Ruby code:
|
306
320
|
|
307
321
|
```rb
|
308
|
-
class
|
322
|
+
class ImageUploader < Shrine
|
323
|
+
plugin :validation_helpers
|
324
|
+
|
309
325
|
Attacher.validate do
|
310
|
-
# validation macros
|
311
326
|
validate_max_size 10*1024*1024
|
312
|
-
|
327
|
+
validate_extension %w[jpg jpeg png webp]
|
328
|
+
|
329
|
+
if validate_mime_type %W[image/jpeg image/png image/webp]
|
330
|
+
validate_max_dimensions [5000, 5000]
|
313
331
|
|
314
|
-
|
315
|
-
|
316
|
-
|
332
|
+
unless ImageProcessing::MiniMagick.valid_image?(file.download.path)
|
333
|
+
error << "seems to be corrupted"
|
334
|
+
end
|
317
335
|
end
|
318
336
|
end
|
319
337
|
end
|
@@ -432,7 +450,6 @@ on top of Rack, so that they can be used with any Ruby web framework.
|
|
432
450
|
[backgrounding libraries]: https://github.com/shrinerb/shrine/wiki/Backgrounding-Libraries
|
433
451
|
[Down streaming]: https://github.com/janko/down#streaming
|
434
452
|
[validation_helpers]: https://shrinerb.com/docs/plugins/validation_helpers
|
435
|
-
[custom validations]: https://shrinerb.com/docs/validation#custom-validations
|
436
453
|
[derivatives]: https://shrinerb.com/docs/plugins/derivatives
|
437
454
|
[derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
|
438
455
|
[libvips performance]: https://github.com/libvips/libvips/wiki/Speed-and-memory-use#results
|
data/doc/attacher.md
CHANGED
@@ -96,14 +96,14 @@ If given a raw file, it will upload it to temporary storage:
|
|
96
96
|
|
97
97
|
```rb
|
98
98
|
attacher.assign(file)
|
99
|
-
attacher.file #=> #<Shrine::UploadedFile
|
99
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:cache ...>
|
100
100
|
```
|
101
101
|
|
102
102
|
If given cached file data (JSON or Hash), it will set the cached file:
|
103
103
|
|
104
104
|
```rb
|
105
105
|
attacher.assign('{"id":"asdf.jpg","storage":"cache","metadata":{...}}')
|
106
|
-
attacher.file #=> #<Shrine::UploadedFile
|
106
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:cache ...>
|
107
107
|
```
|
108
108
|
|
109
109
|
If given an empty string, it will no-op:
|
@@ -130,8 +130,8 @@ attacher.attach_cached(file)
|
|
130
130
|
|
131
131
|
# sets cached file
|
132
132
|
attacher.attach_cached('{"id":"asdf.jpg","storage":"cache","metadata":{...}}')
|
133
|
-
attacher.attach_cached("id" => "asdf.jpg", "storage" => "cache", "metadata" => { ... })
|
134
|
-
attacher.attach_cached(id: "asdf.jpg", storage: "cache", metadata: { ... })
|
133
|
+
attacher.attach_cached({ "id" => "asdf.jpg", "storage" => "cache", "metadata" => { ... } })
|
134
|
+
attacher.attach_cached({ id: "asdf.jpg", storage: "cache", metadata: { ... } })
|
135
135
|
|
136
136
|
# unsets attached file
|
137
137
|
attacher.attach_cached(nil)
|
@@ -143,7 +143,7 @@ The `Attacher#attach` method uploads a given file to permanent storage:
|
|
143
143
|
|
144
144
|
```rb
|
145
145
|
attacher.attach(file)
|
146
|
-
attacher.file #=> #<Shrine::UploadedFile
|
146
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:store ...>
|
147
147
|
```
|
148
148
|
|
149
149
|
This method is useful when attaching files from scripts, where validation
|
@@ -153,7 +153,7 @@ You can specify a different destination storage with the `:storage` option:
|
|
153
153
|
|
154
154
|
```rb
|
155
155
|
attacher.attach(file, storage: :other_store)
|
156
|
-
attacher.file #=> #<Shrine::UploadedFile
|
156
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:other_store ...>
|
157
157
|
```
|
158
158
|
|
159
159
|
Any additional options passed to `Attacher#attach`, `Attacher#attach_cached`
|
@@ -171,9 +171,9 @@ If you want to upload a file to without attaching it, you can use
|
|
171
171
|
`Attacher#upload`:
|
172
172
|
|
173
173
|
```rb
|
174
|
-
attacher.upload(file) #=> #<Shrine::UploadedFile
|
175
|
-
attacher.upload(file, :cache) #=> #<Shrine::UploadedFile
|
176
|
-
attacher.upload(file, :other_store) #=> #<Shrine::UploadedFile
|
174
|
+
attacher.upload(file) #=> #<Shrine::UploadedFile storage=:store ...>
|
175
|
+
attacher.upload(file, :cache) #=> #<Shrine::UploadedFile storage=:cache ...>
|
176
|
+
attacher.upload(file, :other_store) #=> #<Shrine::UploadedFile storage=:other_store ...>
|
177
177
|
```
|
178
178
|
|
179
179
|
This is useful if you want to attacher [context](#context) such as `:record`
|
@@ -202,20 +202,19 @@ attacher.changed? #=> true
|
|
202
202
|
You can use `Attacher#change` to attach an `UploadedFile` object as is:
|
203
203
|
|
204
204
|
```rb
|
205
|
-
uploaded_file #=> #<Shrine::UploadedFile
|
205
|
+
uploaded_file #=> #<Shrine::UploadedFile id="foo" ...>
|
206
206
|
attacher.change(uploaded_file)
|
207
|
-
attacher.file #=> #<Shrine::UploadedFile
|
207
|
+
attacher.file #=> #<Shrine::UploadedFile id="foo" ...>
|
208
208
|
attacher.changed? #=> true
|
209
|
-
|
210
209
|
```
|
211
210
|
|
212
211
|
If you want to attach a file without triggering dirty tracking or validation,
|
213
212
|
you can use `Attacher#set`:
|
214
213
|
|
215
214
|
```rb
|
216
|
-
uploaded_file #=> #<Shrine::UploadedFile
|
215
|
+
uploaded_file #=> #<Shrine::UploadedFile id="foo" ...>
|
217
216
|
attacher.set(uploaded_file)
|
218
|
-
attacher.file #=> #<Shrine::UploadedFile
|
217
|
+
attacher.file #=> #<Shrine::UploadedFile id="foo" ...>
|
219
218
|
attacher.changed? #=> false
|
220
219
|
```
|
221
220
|
|
@@ -246,16 +245,16 @@ storage, and in this case uploads it to permanent storage.
|
|
246
245
|
```rb
|
247
246
|
attacher.attach_cached(io)
|
248
247
|
attacher.finalize # uploads attached file to permanent storage
|
249
|
-
attacher.file #=> #<Shrine::UploadedFile
|
248
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:store ...>
|
250
249
|
```
|
251
250
|
|
252
251
|
Internally it calls `Attacher#promote_cached`, which you can call directly if
|
253
252
|
you want to pass any promote options:
|
254
253
|
|
255
254
|
```rb
|
256
|
-
attacher.file #=> #<Shrine::UploadedFile
|
255
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:cache ...>
|
257
256
|
attacher.promote_cached # uploads attached file to permanent storage if new and cached
|
258
|
-
attacher.file #=> #<Shrine::UploadedFile
|
257
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:store ...>
|
259
258
|
```
|
260
259
|
|
261
260
|
You can also call `Attacher#promote` if you want to upload attached file to
|
data/doc/carrierwave.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
---
|
2
|
-
title:
|
2
|
+
title: Upgrading from CarrierWave
|
3
3
|
---
|
4
4
|
|
5
5
|
This guide is aimed at helping CarrierWave users transition to Shrine, and it
|
6
6
|
consists of three parts:
|
7
7
|
|
8
8
|
1. Explanation of the key differences in design between CarrierWave and Shrine
|
9
|
-
2. Instructions how to migrate
|
9
|
+
2. Instructions how to migrate an existing app that uses CarrierWave to Shrine
|
10
10
|
3. Extensive reference of CarrierWave's interface with Shrine equivalents
|
11
11
|
|
12
12
|
## Overview
|
@@ -159,7 +159,7 @@ require "image_processing/mini_magick"
|
|
159
159
|
class ImageUploader < Shrine
|
160
160
|
plugin :derivatives
|
161
161
|
|
162
|
-
Attacher.
|
162
|
+
Attacher.derivatives do |original|
|
163
163
|
magick = ImageProcessing::MiniMagick.source(original)
|
164
164
|
|
165
165
|
{
|
@@ -179,15 +179,15 @@ uploaded processed files into the database (including any extracted metadata),
|
|
179
179
|
which then becomes the source of truth on which versions have been generated.
|
180
180
|
|
181
181
|
```rb
|
182
|
-
photo.image #=> #<Shrine::UploadedFile
|
182
|
+
photo.image #=> #<Shrine::UploadedFile id="original.jpg" ...>
|
183
183
|
photo.image_derivatives #=> {}
|
184
184
|
|
185
185
|
photo.image_derivatives! # triggers processing
|
186
186
|
photo.image_derivatives #=>
|
187
187
|
# {
|
188
|
-
# large:
|
189
|
-
# medium: #<Shrine::UploadedFile
|
190
|
-
# small:
|
188
|
+
# large: #<Shrine::UploadedFile id="large.jpg" metadata={"size"=>873232, ...} ...>,
|
189
|
+
# medium: #<Shrine::UploadedFile id="medium.jpg" metadata={"size"=>94823, ...} ...>,
|
190
|
+
# small: #<Shrine::UploadedFile id="small.jpg" metadata={"size"=>37322, ...} ...>,
|
191
191
|
# }
|
192
192
|
```
|
193
193
|
|
@@ -268,18 +268,24 @@ Files] guide explains this setup in more detail.
|
|
268
268
|
## Migrating from CarrierWave
|
269
269
|
|
270
270
|
You have an existing app using CarrierWave and you want to transfer it to
|
271
|
-
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
272
|
-
|
271
|
+
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
272
|
+
|
273
|
+
### 1. Add Shrine column
|
274
|
+
|
275
|
+
First we need to create the `image_data` column for Shrine:
|
273
276
|
|
274
277
|
```rb
|
275
278
|
add_column :photos, :image_data, :text # or :json or :jsonb if supported
|
276
279
|
```
|
277
280
|
|
278
|
-
|
279
|
-
|
280
|
-
attachments
|
281
|
+
### 2. Dual write
|
282
|
+
|
283
|
+
Next, we need to make new CarrierWave attachments write to the
|
284
|
+
`image_data` column. This can be done by including the below module to all
|
285
|
+
models that have CarrierWave attachments:
|
281
286
|
|
282
287
|
```rb
|
288
|
+
# config/initializers/shrine.rb (Rails)
|
283
289
|
require "shrine"
|
284
290
|
|
285
291
|
Shrine.storages = {
|
@@ -289,8 +295,7 @@ Shrine.storages = {
|
|
289
295
|
|
290
296
|
Shrine.plugin :model
|
291
297
|
Shrine.plugin :derivatives
|
292
|
-
|
293
|
-
```rb
|
298
|
+
|
294
299
|
module CarrierwaveShrineSynchronization
|
295
300
|
def self.included(model)
|
296
301
|
model.before_save do
|
@@ -302,13 +307,13 @@ module CarrierwaveShrineSynchronization
|
|
302
307
|
|
303
308
|
def write_shrine_data(name)
|
304
309
|
uploader = send(name)
|
305
|
-
attacher = Shrine::Attacher.
|
310
|
+
attacher = Shrine::Attacher.from_model(self, name)
|
306
311
|
|
307
312
|
if read_attribute(name).present?
|
308
313
|
attacher.set shrine_file(uploader)
|
309
314
|
|
310
|
-
uploader.versions.each do |
|
311
|
-
attacher.merge_derivatives(
|
315
|
+
uploader.versions.each do |version_name, version|
|
316
|
+
attacher.merge_derivatives(version_name => shrine_file(version))
|
312
317
|
end
|
313
318
|
else
|
314
319
|
attacher.set nil
|
@@ -340,20 +345,27 @@ end
|
|
340
345
|
```
|
341
346
|
|
342
347
|
After you deploy this code, the `image_data` column should now be successfully
|
343
|
-
synchronized with new attachments.
|
344
|
-
|
348
|
+
synchronized with new attachments.
|
349
|
+
|
350
|
+
### 3. Data migration
|
351
|
+
|
352
|
+
Next step is to run a script which writes all existing CarrierWave attachments
|
353
|
+
to `image_data`:
|
345
354
|
|
346
355
|
```rb
|
347
356
|
Photo.find_each do |photo|
|
348
|
-
|
357
|
+
photo.write_shrine_data(:image)
|
349
358
|
photo.save!
|
350
359
|
end
|
351
360
|
```
|
352
361
|
|
362
|
+
### 4. Rewrite code
|
363
|
+
|
353
364
|
Now you should be able to rewrite your application so that it uses Shrine
|
354
|
-
instead of CarrierWave
|
355
|
-
|
356
|
-
|
365
|
+
instead of CarrierWave (you can consult the reference in the next section). You
|
366
|
+
can remove the `CarrierwaveShrineSynchronization` module as well.
|
367
|
+
|
368
|
+
### 5. Backill metadata
|
357
369
|
|
358
370
|
You'll notice that Shrine metadata will be absent from the migrated files'
|
359
371
|
data. You can run a script that will fill in any missing metadata defined in
|
@@ -363,11 +375,20 @@ your Shrine uploader:
|
|
363
375
|
Shrine.plugin :refresh_metadata
|
364
376
|
|
365
377
|
Photo.find_each do |photo|
|
366
|
-
photo.image_attacher
|
367
|
-
|
378
|
+
attacher = photo.image_attacher
|
379
|
+
attacher.refresh_metadata!
|
380
|
+
attacher.atomic_persist
|
368
381
|
end
|
369
382
|
```
|
370
383
|
|
384
|
+
### 6. Remove CarrierWave column
|
385
|
+
|
386
|
+
If everything is looking good, we can remove the CarrierWave column:
|
387
|
+
|
388
|
+
```rb
|
389
|
+
remove_column :photos, :image
|
390
|
+
```
|
391
|
+
|
371
392
|
## CarrierWave to Shrine direct mapping
|
372
393
|
|
373
394
|
### `CarrierWave::Uploader::Base`
|
@@ -395,7 +416,7 @@ Processing is defined by using the `derivatives` plugin:
|
|
395
416
|
class ImageUploader < Shrine
|
396
417
|
plugin :derivatives
|
397
418
|
|
398
|
-
Attacher.
|
419
|
+
Attacher.derivatives do |original|
|
399
420
|
magick = ImageProcessing::MiniMagick.source(image)
|
400
421
|
|
401
422
|
{
|
@@ -455,16 +476,25 @@ photo.image.original_filename #=> "avatar.jpg"
|
|
455
476
|
|
456
477
|
#### `#store_dir`, `#cache_dir`
|
457
478
|
|
458
|
-
Shrine here provides a `#generate_location` method
|
459
|
-
storages:
|
479
|
+
Shrine here provides a single `#generate_location` method that's triggered for
|
480
|
+
all storages:
|
460
481
|
|
461
482
|
```rb
|
462
483
|
class ImageUploader < Shrine
|
463
|
-
def generate_location(io, record: nil, **)
|
464
|
-
|
484
|
+
def generate_location(io, record: nil, name: nil, **)
|
485
|
+
[ storage_key,
|
486
|
+
record && record.class.name.underscore,
|
487
|
+
record && record.id,
|
488
|
+
super,
|
489
|
+
io.original_filename ].compact.join("/")
|
465
490
|
end
|
466
491
|
end
|
467
492
|
```
|
493
|
+
```
|
494
|
+
cache/user/123/2feff8c724e7ce17/nature.jpg
|
495
|
+
store/user/456/7f99669fde1e01fc/kitten.jpg
|
496
|
+
...
|
497
|
+
```
|
468
498
|
|
469
499
|
You might also want to use the `pretty_location` plugin for automatically
|
470
500
|
generating an organized folder structure.
|
@@ -477,8 +507,8 @@ For default URLs you can use the `default_url` plugin:
|
|
477
507
|
class ImageUploader < Shrine
|
478
508
|
plugin :default_url
|
479
509
|
|
480
|
-
Attacher.default_url do |
|
481
|
-
"/
|
510
|
+
Attacher.default_url do |derivative: nil, **|
|
511
|
+
"/fallbacks/#{derivative || "original"}.jpg"
|
482
512
|
end
|
483
513
|
end
|
484
514
|
```
|
@@ -499,7 +529,7 @@ class ImageUploader < Shrine
|
|
499
529
|
end
|
500
530
|
```
|
501
531
|
|
502
|
-
####
|
532
|
+
#### `#content_type_whitelist`, `#content_type_blacklist`
|
503
533
|
|
504
534
|
In Shrine, MIME type whitelisting/blacklisting is part of validations, and is
|
505
535
|
provided by the `validation_helpers` plugin, though it doesn't support regexes:
|
@@ -515,6 +545,17 @@ class ImageUploader < Shrine
|
|
515
545
|
end
|
516
546
|
```
|
517
547
|
|
548
|
+
Make sure to also load the `determine_mime_type` plugin to detect MIME type
|
549
|
+
from file content.
|
550
|
+
|
551
|
+
```rb
|
552
|
+
# Gemfile
|
553
|
+
gem "mimemagic"
|
554
|
+
```
|
555
|
+
```rb
|
556
|
+
Shrine.plugin :determine_mime_type, analyzer: :mimemagic
|
557
|
+
```
|
558
|
+
|
518
559
|
#### `#size_range`
|
519
560
|
|
520
561
|
In Shrine file size validations are typically done using the
|
@@ -622,7 +663,7 @@ shows what are Shrine's equivalents.
|
|
622
663
|
|
623
664
|
#### `root`, `base_path`, `permissions`, `directory_permissions`
|
624
665
|
|
625
|
-
In Shrine these are configured on the FileSystem storage directly.
|
666
|
+
In Shrine these are configured on the `FileSystem` storage directly.
|
626
667
|
|
627
668
|
#### `storage`, `storage_engines`
|
628
669
|
|