shrine 2.19.3 → 3.6.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +523 -41
- data/LICENSE.txt +1 -1
- data/README.md +83 -979
- data/doc/advantages.md +231 -204
- data/doc/attacher.md +304 -153
- data/doc/carrierwave.md +297 -226
- data/doc/changing_derivatives.md +308 -0
- data/doc/changing_location.md +103 -21
- data/doc/changing_storage.md +110 -0
- data/doc/creating_persistence_plugins.md +132 -0
- data/doc/creating_plugins.md +43 -23
- data/doc/creating_storages.md +19 -5
- data/doc/design.md +147 -97
- data/doc/direct_s3.md +38 -28
- data/doc/external/articles.md +63 -0
- data/doc/external/extensions.md +53 -0
- data/doc/external/misc.md +32 -0
- data/doc/getting_started.md +1156 -0
- data/doc/metadata.md +190 -109
- data/doc/multiple_files.md +93 -30
- data/doc/paperclip.md +384 -262
- data/doc/plugins/activerecord.md +177 -46
- data/doc/plugins/add_metadata.md +139 -38
- data/doc/plugins/atomic_helpers.md +217 -0
- data/doc/plugins/backgrounding.md +156 -98
- data/doc/plugins/cached_attachment_data.md +7 -5
- data/doc/plugins/column.md +121 -0
- data/doc/plugins/data_uri.md +23 -22
- data/doc/plugins/default_storage.md +36 -10
- data/doc/plugins/default_url.md +30 -13
- data/doc/plugins/delete_raw.md +4 -2
- data/doc/plugins/derivation_endpoint.md +186 -101
- data/doc/plugins/derivatives.md +839 -0
- data/doc/plugins/determine_mime_type.md +4 -2
- data/doc/plugins/download_endpoint.md +64 -8
- data/doc/plugins/dynamic_storage.md +5 -3
- data/doc/plugins/entity.md +263 -0
- data/doc/plugins/form_assign.md +55 -0
- data/doc/plugins/included.md +31 -8
- data/doc/plugins/infer_extension.md +21 -10
- data/doc/plugins/instrumentation.md +38 -16
- data/doc/plugins/keep_files.md +16 -17
- data/doc/plugins/metadata_attributes.md +42 -13
- data/doc/plugins/mirroring.md +118 -0
- data/doc/plugins/model.md +210 -0
- data/doc/plugins/module_include.md +4 -2
- data/doc/plugins/multi_cache.md +24 -0
- data/doc/plugins/persistence.md +101 -0
- data/doc/plugins/presign_endpoint.md +9 -4
- data/doc/plugins/pretty_location.md +16 -3
- data/doc/plugins/processing.md +4 -2
- data/doc/plugins/rack_file.md +8 -2
- data/doc/plugins/rack_response.md +6 -2
- data/doc/plugins/recache.md +4 -2
- data/doc/plugins/refresh_metadata.md +49 -9
- data/doc/plugins/remote_url.md +84 -47
- data/doc/plugins/remove_attachment.md +27 -6
- data/doc/plugins/remove_invalid.md +21 -6
- data/doc/plugins/restore_cached_data.md +11 -3
- data/doc/plugins/sequel.md +159 -35
- data/doc/plugins/signature.md +16 -5
- data/doc/plugins/store_dimensions.md +14 -2
- data/doc/plugins/tempfile.md +4 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +13 -13
- data/doc/plugins/upload_options.md +6 -4
- data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
- data/doc/plugins/validation.md +97 -0
- data/doc/plugins/validation_helpers.md +16 -13
- data/doc/plugins/versions.md +15 -19
- data/doc/processing.md +438 -221
- data/doc/refile.md +188 -170
- data/doc/release_notes/1.0.0.md +4 -0
- data/doc/release_notes/1.1.0.md +6 -2
- data/doc/release_notes/1.2.0.md +4 -0
- data/doc/release_notes/1.3.0.md +4 -0
- data/doc/release_notes/1.4.0.md +4 -0
- data/doc/release_notes/1.4.1.md +4 -0
- data/doc/release_notes/1.4.2.md +4 -0
- data/doc/release_notes/2.0.0.md +4 -0
- data/doc/release_notes/2.0.1.md +4 -0
- data/doc/release_notes/2.1.0.md +5 -1
- data/doc/release_notes/2.1.1.md +4 -0
- data/doc/release_notes/2.10.0.md +4 -0
- data/doc/release_notes/2.10.1.md +4 -0
- data/doc/release_notes/2.11.0.md +4 -0
- data/doc/release_notes/2.12.0.md +4 -0
- data/doc/release_notes/2.13.0.md +4 -0
- data/doc/release_notes/2.14.0.md +5 -1
- data/doc/release_notes/2.15.0.md +11 -7
- data/doc/release_notes/2.16.0.md +4 -0
- data/doc/release_notes/2.17.0.md +4 -0
- data/doc/release_notes/2.18.0.md +4 -0
- data/doc/release_notes/2.19.0.md +6 -3
- data/doc/release_notes/2.2.0.md +4 -0
- data/doc/release_notes/2.3.0.md +4 -0
- data/doc/release_notes/2.3.1.md +4 -0
- data/doc/release_notes/2.4.0.md +4 -0
- data/doc/release_notes/2.4.1.md +4 -0
- data/doc/release_notes/2.5.0.md +4 -0
- data/doc/release_notes/2.6.0.md +4 -0
- data/doc/release_notes/2.6.1.md +4 -0
- data/doc/release_notes/2.7.0.md +4 -0
- data/doc/release_notes/2.8.0.md +4 -0
- data/doc/release_notes/2.9.0.md +4 -0
- data/doc/release_notes/3.0.0.md +981 -0
- 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 +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/release_notes/3.4.0.md +35 -0
- data/doc/release_notes/3.5.0.md +63 -0
- data/doc/release_notes/3.6.0.md +23 -0
- data/doc/retrieving_uploads.md +5 -2
- data/doc/securing_uploads.md +60 -37
- data/doc/storage/file_system.md +20 -3
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +122 -78
- data/doc/testing.md +141 -133
- data/doc/upgrading_to_3.md +708 -0
- data/doc/validation.md +54 -90
- data/lib/shrine/attacher.rb +292 -169
- data/lib/shrine/attachment.rb +13 -46
- data/lib/shrine/plugins/_persistence.rb +93 -0
- data/lib/shrine/plugins/activerecord.rb +77 -34
- data/lib/shrine/plugins/add_metadata.rb +25 -17
- data/lib/shrine/plugins/atomic_helpers.rb +119 -0
- data/lib/shrine/plugins/backgrounding.rb +77 -113
- data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
- data/lib/shrine/plugins/column.rb +102 -0
- data/lib/shrine/plugins/data_uri.rb +38 -36
- data/lib/shrine/plugins/default_storage.rb +45 -15
- data/lib/shrine/plugins/default_url.rb +12 -24
- data/lib/shrine/plugins/default_url_options.rb +3 -30
- data/lib/shrine/plugins/delete_raw.rb +10 -16
- data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
- data/lib/shrine/plugins/derivatives.rb +645 -0
- data/lib/shrine/plugins/determine_mime_type.rb +9 -21
- data/lib/shrine/plugins/download_endpoint.rb +118 -133
- data/lib/shrine/plugins/dynamic_storage.rb +5 -11
- data/lib/shrine/plugins/entity.rb +158 -0
- data/lib/shrine/plugins/form_assign.rb +108 -0
- data/lib/shrine/plugins/included.rb +6 -6
- data/lib/shrine/plugins/infer_extension.rb +17 -20
- data/lib/shrine/plugins/instrumentation.rb +59 -43
- data/lib/shrine/plugins/keep_files.rb +3 -15
- data/lib/shrine/plugins/metadata_attributes.rb +28 -19
- data/lib/shrine/plugins/mirroring.rb +142 -0
- data/lib/shrine/plugins/model.rb +160 -0
- data/lib/shrine/plugins/module_include.rb +3 -3
- data/lib/shrine/plugins/multi_cache.rb +27 -0
- data/lib/shrine/plugins/presign_endpoint.rb +27 -28
- data/lib/shrine/plugins/pretty_location.rb +15 -9
- data/lib/shrine/plugins/processing.rb +22 -9
- data/lib/shrine/plugins/rack_file.rb +2 -42
- data/lib/shrine/plugins/rack_response.rb +21 -10
- data/lib/shrine/plugins/recache.rb +6 -5
- data/lib/shrine/plugins/refresh_metadata.rb +13 -11
- data/lib/shrine/plugins/remote_url.rb +49 -49
- data/lib/shrine/plugins/remove_attachment.rb +12 -6
- data/lib/shrine/plugins/remove_invalid.rb +19 -8
- data/lib/shrine/plugins/restore_cached_data.rb +13 -7
- data/lib/shrine/plugins/sequel.rb +86 -36
- data/lib/shrine/plugins/signature.rb +10 -16
- data/lib/shrine/plugins/store_dimensions.rb +35 -40
- data/lib/shrine/plugins/tempfile.rb +1 -3
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +28 -24
- data/lib/shrine/plugins/upload_options.rb +14 -15
- data/lib/shrine/plugins/url_options.rb +31 -0
- data/lib/shrine/plugins/validation.rb +80 -0
- data/lib/shrine/plugins/validation_helpers.rb +35 -58
- data/lib/shrine/plugins/versions.rb +107 -87
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/storage/file_system.rb +46 -64
- data/lib/shrine/storage/linter.rb +42 -7
- data/lib/shrine/storage/memory.rb +49 -0
- data/lib/shrine/storage/s3.rb +173 -160
- data/lib/shrine/uploaded_file.rb +32 -32
- data/lib/shrine/version.rb +3 -3
- data/lib/shrine.rb +87 -150
- data/shrine.gemspec +11 -12
- metadata +92 -82
- data/doc/migrating_storage.md +0 -76
- data/doc/plugins/backup.md +0 -31
- data/doc/plugins/copy.md +0 -24
- data/doc/plugins/delete_promoted.md +0 -12
- data/doc/plugins/direct_upload.md +0 -172
- data/doc/plugins/hooks.md +0 -58
- data/doc/plugins/logging.md +0 -42
- data/doc/plugins/migration_helpers.md +0 -60
- data/doc/plugins/moving.md +0 -19
- data/doc/plugins/multi_delete.md +0 -20
- data/doc/plugins/parallelize.md +0 -16
- data/doc/plugins/parsed_json.md +0 -23
- data/doc/regenerating_versions.md +0 -143
- data/lib/shrine/plugins/background_helpers.rb +0 -5
- data/lib/shrine/plugins/backup.rb +0 -90
- data/lib/shrine/plugins/copy.rb +0 -50
- data/lib/shrine/plugins/delete_promoted.rb +0 -20
- data/lib/shrine/plugins/direct_upload.rb +0 -217
- data/lib/shrine/plugins/hooks.rb +0 -90
- data/lib/shrine/plugins/logging.rb +0 -142
- data/lib/shrine/plugins/migration_helpers.rb +0 -70
- data/lib/shrine/plugins/moving.rb +0 -57
- data/lib/shrine/plugins/multi_delete.rb +0 -32
- data/lib/shrine/plugins/parallelize.rb +0 -78
- data/lib/shrine/plugins/parsed_json.rb +0 -29
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Determine MIME Type
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
The [`determine_mime_type`][determine_mime_type] plugin allows you to determine
|
|
4
6
|
and store the actual MIME type of the file analyzed from file content.
|
|
@@ -125,7 +127,7 @@ Or disable logging altogether:
|
|
|
125
127
|
plugin :determine_mime_type, log_subscriber: nil
|
|
126
128
|
```
|
|
127
129
|
|
|
128
|
-
[determine_mime_type]: /lib/shrine/plugins/determine_mime_type.rb
|
|
130
|
+
[determine_mime_type]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/determine_mime_type.rb
|
|
129
131
|
[file]: http://linux.die.net/man/1/file
|
|
130
132
|
[Windows equivalent]: http://gnuwin32.sourceforge.net/packages/file.htm
|
|
131
133
|
[ruby-filemagic]: https://github.com/blackwinter/ruby-filemagic
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Download Endpoint
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
The [`download_endpoint`][download_endpoint] plugin provides a Rack app for
|
|
4
6
|
downloading uploaded files from specified storages. This can be useful when
|
|
5
7
|
files from your storage isn't accessible over URL (e.g. database storages) or
|
|
6
8
|
if you want to authenticate your downloads.
|
|
7
9
|
|
|
10
|
+
## Global Endpoint
|
|
11
|
+
|
|
8
12
|
You can configure the plugin with the path prefix which the endpoint will be
|
|
9
13
|
mounted on.
|
|
10
14
|
|
|
11
15
|
```rb
|
|
12
|
-
plugin :download_endpoint, prefix: "attachments"
|
|
16
|
+
Shrine.plugin :download_endpoint, prefix: "attachments"
|
|
13
17
|
```
|
|
14
18
|
|
|
15
19
|
The plugin adds a `Shrine.download_endpoint` method which returns a Rack
|
|
@@ -30,6 +34,62 @@ Links to the download endpoint are generated by calling
|
|
|
30
34
|
```rb
|
|
31
35
|
uploaded_file.download_url #=> "/attachments/eyJpZCI6ImFkdzlyeTM..."
|
|
32
36
|
```
|
|
37
|
+
## Endpoint via Uploader
|
|
38
|
+
|
|
39
|
+
You can also configure the plugin in the uploader directly - just make sure to mount it via your Uploader-class.
|
|
40
|
+
|
|
41
|
+
```rb
|
|
42
|
+
class ImageUploader < Shrine
|
|
43
|
+
plugin :download_endpoint, prefix: "images"
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```rb
|
|
48
|
+
# config/routes.rb (Rails)
|
|
49
|
+
Rails.application.routes.draw do
|
|
50
|
+
# ...
|
|
51
|
+
mount ImageUploader.download_endpoint => "/images"
|
|
52
|
+
end
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
*Hint: For shrine versions 2.x -> ensure that you don't include the plugin
|
|
56
|
+
twice (globally and in your uploader class - see #408)*
|
|
57
|
+
|
|
58
|
+
## Calling from a controller
|
|
59
|
+
|
|
60
|
+
If you want to run additional code around the download (such as authentication),
|
|
61
|
+
mounting the download endpoint in your router might be limiting. You can instead
|
|
62
|
+
create a custom controller action and handle download requests there using
|
|
63
|
+
`Shrine.download_response`:
|
|
64
|
+
|
|
65
|
+
```rb
|
|
66
|
+
# config/routes.rb (Rails)
|
|
67
|
+
Rails.application.routes.draw do
|
|
68
|
+
# ...
|
|
69
|
+
get "/attachments/*rest", to: "downloads#image"
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
```rb
|
|
73
|
+
# app/controllers/downloads_controller.rb (Rails)
|
|
74
|
+
class DownloadsController < ApplicationController
|
|
75
|
+
def image
|
|
76
|
+
# ... we can perform authentication here ...
|
|
77
|
+
set_rack_response ImageUploader.download_response(request.env)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def set_rack_response((status, headers, body))
|
|
83
|
+
self.status = status
|
|
84
|
+
self.headers.merge!(headers)
|
|
85
|
+
self.response_body = body
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If you want to create an endpoint with a custom path, you can use the
|
|
91
|
+
[`rack_response`][rack_response] plugin directly, which this plugin uses
|
|
92
|
+
internally.
|
|
33
93
|
|
|
34
94
|
## Host
|
|
35
95
|
|
|
@@ -99,11 +159,6 @@ You can override any of the options above when creating the endpoint:
|
|
|
99
159
|
Shrine.download_endpoint(disposition: "attachment")
|
|
100
160
|
```
|
|
101
161
|
|
|
102
|
-
## Custom endpoint
|
|
103
|
-
|
|
104
|
-
If you want to have more control on download requests, you can use the
|
|
105
|
-
`rack_response` plugin which this plugin uses internally.
|
|
106
|
-
|
|
107
162
|
## Plugin options
|
|
108
163
|
|
|
109
164
|
| Name | Description | Default |
|
|
@@ -114,4 +169,5 @@ If you want to have more control on download requests, you can use the
|
|
|
114
169
|
| `:prefix` | Path prefix prepended to download URLs | `nil` |
|
|
115
170
|
| `:redirect` | Whether to redirect to uploaded files on the storage | `false` |
|
|
116
171
|
|
|
117
|
-
[download_endpoint]: /lib/shrine/plugins/download_endpoint.rb
|
|
172
|
+
[download_endpoint]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/download_endpoint.rb
|
|
173
|
+
[rack_response]: https://shrinerb.com/docs/plugins/rack_response
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Dynamic Storage
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
The [`dynamic_storage`][dynamic_storage] plugin allows you to register a
|
|
4
6
|
storage using a regex, and evaluate the storage class dynamically depending on
|
|
@@ -10,7 +12,7 @@ Example:
|
|
|
10
12
|
plugin :dynamic_storage
|
|
11
13
|
|
|
12
14
|
storage /store_(\w+)/ do |match|
|
|
13
|
-
Shrine::
|
|
15
|
+
Shrine::Storage::S3.new(bucket: match[1])
|
|
14
16
|
end
|
|
15
17
|
```
|
|
16
18
|
|
|
@@ -20,4 +22,4 @@ the bucket "foo". The block is yielded an instance of `MatchData`.
|
|
|
20
22
|
|
|
21
23
|
This can be useful in combination with the `default_storage` plugin.
|
|
22
24
|
|
|
23
|
-
[dynamic_storage]: /lib/shrine/plugins/dynamic_storage.rb
|
|
25
|
+
[dynamic_storage]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/dynamic_storage.rb
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Entity
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The [`entity`][entity] plugin provides integration for handling attachments on
|
|
6
|
+
immutable structs. It is built on top of the [`column`][column] plugin.
|
|
7
|
+
|
|
8
|
+
```rb
|
|
9
|
+
plugin :entity
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Attachment
|
|
13
|
+
|
|
14
|
+
Including a `Shrine::Attachment` module into an entity class will add the
|
|
15
|
+
following instance methods:
|
|
16
|
+
|
|
17
|
+
* `#<name>` – returns the attached file
|
|
18
|
+
* `#<name>_url` – returns the attached file URL
|
|
19
|
+
* `#<name>_attacher` – returns a `Shrine::Attacher` instance
|
|
20
|
+
|
|
21
|
+
These methods read attachment data from the `#<name>_data` attribute on the
|
|
22
|
+
entity instance.
|
|
23
|
+
|
|
24
|
+
```rb
|
|
25
|
+
class Photo
|
|
26
|
+
attr_reader :image_data
|
|
27
|
+
|
|
28
|
+
include ImageUploader::Attachment(:image)
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
```rb
|
|
32
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
|
33
|
+
photo.image #=> #<ImageUploader::UploadedFile>
|
|
34
|
+
photo.image_url #=> "https://example.com/image.jpg"
|
|
35
|
+
photo.image_attacher #=> #<ImageUploader::Attacher>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### `#<name>`
|
|
39
|
+
|
|
40
|
+
Calls `Attacher#get`, which returns an `UploadedFile` object instantiated from
|
|
41
|
+
attachment data.
|
|
42
|
+
|
|
43
|
+
```rb
|
|
44
|
+
photo = Photo.new(image_data: '{"id":"foo.jpg","storage":"store","metadata":{...}}')
|
|
45
|
+
photo.image #=> #<ImageUploader::UploadedFile>
|
|
46
|
+
photo.image.id #=> "foo.jpg"
|
|
47
|
+
photo.image.storage_key #=> :store
|
|
48
|
+
photo.image.metadata #=> { ... }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If no file is attached, `nil` is returned.
|
|
52
|
+
|
|
53
|
+
```rb
|
|
54
|
+
photo = Photo.new(image_data: nil)
|
|
55
|
+
photo.image #=> nil
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### `#<name>_url`
|
|
59
|
+
|
|
60
|
+
Calls `Attacher#url`, which returns the URL to the attached file.
|
|
61
|
+
|
|
62
|
+
```rb
|
|
63
|
+
photo = Photo.new(image_data: {"id":"foo.jpg","storage":"...","metadata":{...}})
|
|
64
|
+
photo.image_url #=> "https://example.com/foo.jpg"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If no file is attached, `nil` is returned.
|
|
68
|
+
|
|
69
|
+
```rb
|
|
70
|
+
photo = Photo.new(image_data: nil)
|
|
71
|
+
photo.image_url #=> nil
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### `#<name>_attacher`
|
|
75
|
+
|
|
76
|
+
Calls `Attacher.from_entity`, which returns an `Attacher` instance backed by
|
|
77
|
+
the entity object.
|
|
78
|
+
|
|
79
|
+
```rb
|
|
80
|
+
photo = Photo.new
|
|
81
|
+
photo.image_attacher #=> #<ImageUploader::Attacher>
|
|
82
|
+
photo.image_attacher.record #=> #<Photo>
|
|
83
|
+
photo.image_attacher.name #=> :image
|
|
84
|
+
photo.image_attacher.attribute #=> :image_data
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Any additional options will be forwarded to `Attacher#initialize`.
|
|
88
|
+
|
|
89
|
+
```rb
|
|
90
|
+
photo = Photo.new
|
|
91
|
+
attacher = photo.image_attacher(cache: :other_cache)
|
|
92
|
+
attacher.cache_key #=> :other_cache
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
You can also specify default attacher options when including
|
|
96
|
+
`Shrine::Attachment`:
|
|
97
|
+
|
|
98
|
+
```rb
|
|
99
|
+
class Photo
|
|
100
|
+
attr_reader :image_data
|
|
101
|
+
|
|
102
|
+
include ImageUploader::Attachment(:image, store: :other_store)
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
```rb
|
|
106
|
+
photo = Photo.new
|
|
107
|
+
attacher = photo.image_attacher
|
|
108
|
+
attacher.store_key #=> :other_store
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
You can retrieve an `Attacher` instance from the entity *class* as well. In
|
|
112
|
+
this case it will not be initialized with any entity instance.
|
|
113
|
+
|
|
114
|
+
```rb
|
|
115
|
+
attacher = Photo.image_attacher
|
|
116
|
+
attacher #=> #<ImageUploader::Attacher>
|
|
117
|
+
attacher.record #=> nil
|
|
118
|
+
attacher.name #=> nil
|
|
119
|
+
|
|
120
|
+
attacher = Photo.image_attacher(store: :other_store)
|
|
121
|
+
attacher.store_key #=> :other_store
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Attacher
|
|
125
|
+
|
|
126
|
+
You can also use `Shrine::Attacher` directly (with or without the
|
|
127
|
+
`Shrine::Attachment` module):
|
|
128
|
+
|
|
129
|
+
```rb
|
|
130
|
+
class Photo
|
|
131
|
+
attr_reader :image_data
|
|
132
|
+
end
|
|
133
|
+
```
|
|
134
|
+
```rb
|
|
135
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
|
136
|
+
attacher = ImageUploader::Attacher.from_entity(photo, :image)
|
|
137
|
+
|
|
138
|
+
attacher.file #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:store ...>
|
|
139
|
+
|
|
140
|
+
attacher.attach(file)
|
|
141
|
+
attacher.file #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
|
|
142
|
+
attacher.column_values #=> { image_data: '{"id":"397eca.jpg","storage":"store","metadata":{...}}' }
|
|
143
|
+
|
|
144
|
+
photo = Photo.new(attacher.column_values)
|
|
145
|
+
attacher = ImageUploader::Attacher.from_entity(photo, :image)
|
|
146
|
+
|
|
147
|
+
attacher.file #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Loading entity
|
|
151
|
+
|
|
152
|
+
The `Attacher.from_entity` method can be used for creating an `Attacher`
|
|
153
|
+
instance backed by an entity object.
|
|
154
|
+
|
|
155
|
+
```rb
|
|
156
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
|
157
|
+
attacher = ImageUploader::Attacher.from_entity(photo, :image)
|
|
158
|
+
|
|
159
|
+
attacher.record #=> #<Photo>
|
|
160
|
+
attacher.name #=> :image
|
|
161
|
+
attacher.attribute #=> :image_data
|
|
162
|
+
|
|
163
|
+
attacher.file #=> #<ImageUploader::UploadedFile>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Any additional options are forwarded to `Attacher#initialize`.
|
|
167
|
+
|
|
168
|
+
```rb
|
|
169
|
+
attacher = ImageUploader::Attacher.from_entity(photo, :image, cache: :other_cache)
|
|
170
|
+
attacher.cache_key #=> :other_cache
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
You can also load an entity into an existing attacher with
|
|
174
|
+
`Attacher#load_entity`.
|
|
175
|
+
|
|
176
|
+
```rb
|
|
177
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
|
178
|
+
|
|
179
|
+
attacher.load_entity(photo, :image)
|
|
180
|
+
attacher.record #=> #<Photo>
|
|
181
|
+
attacher.name #=> :image
|
|
182
|
+
attacher.file #=> #<ImageUploader::UploadedFile>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Or just `Attacher#set_entity` if you don't want to load attachment data:
|
|
186
|
+
|
|
187
|
+
```rb
|
|
188
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
|
189
|
+
|
|
190
|
+
attacher.set_entity(photo, :image) # doesn't load attachment data
|
|
191
|
+
attacher.record #=> #<Photo>
|
|
192
|
+
attacher.name #=> :image
|
|
193
|
+
attacher.file #=> nil
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Reloading
|
|
197
|
+
|
|
198
|
+
The `Attacher#reload` method reloads attached file from the attachment data on
|
|
199
|
+
the entity attribute and resets dirty tracking.
|
|
200
|
+
|
|
201
|
+
```rb
|
|
202
|
+
photo = Photo.new
|
|
203
|
+
|
|
204
|
+
attacher = ImageUploader::Attacher.from_entity(photo, :image)
|
|
205
|
+
attacher.file #=> nil
|
|
206
|
+
|
|
207
|
+
photo.image_data = '{"id":"...","storage":"...","metadata":{...}}'
|
|
208
|
+
|
|
209
|
+
attacher.file #=> nil
|
|
210
|
+
attacher.reload
|
|
211
|
+
attacher.file #=> #<ImageUploader::UploadedFile>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
If you want to reload attachment data while retaining dirty tracking state, use
|
|
215
|
+
`Attacher#read` instead.
|
|
216
|
+
|
|
217
|
+
### Column values
|
|
218
|
+
|
|
219
|
+
The `Attacher#column_values` method returns a hash with the entity attribute as
|
|
220
|
+
key and current attachment data as value.
|
|
221
|
+
|
|
222
|
+
```rb
|
|
223
|
+
attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
|
|
224
|
+
attacher.attach(io)
|
|
225
|
+
|
|
226
|
+
attacher.column_values #=> { :image_data => '{"id":"...","storage":"...","metadata":{...}}' }
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The `Attacher#attribute` method returns just the entity attribute from which
|
|
230
|
+
attached file data is read.
|
|
231
|
+
|
|
232
|
+
```rb
|
|
233
|
+
attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
|
|
234
|
+
attacher.attribute #=> :image_data
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Entity data
|
|
238
|
+
|
|
239
|
+
The `Attacher#record` method returns the entity instance from which the
|
|
240
|
+
attacher was loaded.
|
|
241
|
+
|
|
242
|
+
```rb
|
|
243
|
+
attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
|
|
244
|
+
attacher.record #=> #<Photo>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The `Attacher#name` method returns the name of the attachment from which the
|
|
248
|
+
attacher was loaded.
|
|
249
|
+
|
|
250
|
+
```rb
|
|
251
|
+
attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
|
|
252
|
+
attacher.name #=> :image
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Serialization
|
|
256
|
+
|
|
257
|
+
By default, attachment data is serialized into JSON using the `JSON` standard
|
|
258
|
+
library. If you want to change how data is serialized, see the
|
|
259
|
+
[`column`][column serializer] plugin docs.
|
|
260
|
+
|
|
261
|
+
[entity]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/entity.rb
|
|
262
|
+
[column]: https://shrinerb.com/docs/plugins/column
|
|
263
|
+
[column serializer]: https://shrinerb.com/docs/plugins/column#serializer
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Form Assign
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The [`form_assign`][form_assign] plugin allows attaching file from form params
|
|
6
|
+
without a form object.
|
|
7
|
+
|
|
8
|
+
```rb
|
|
9
|
+
plugin :form_assign
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The `Attacher#form_assign` method will detect the file param and assign it to
|
|
13
|
+
the attacher:
|
|
14
|
+
|
|
15
|
+
```rb
|
|
16
|
+
attacher = photo.image_attacher
|
|
17
|
+
attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
|
|
18
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
It works with `remote_url`, `data_uri`, and `remove_attachment` plugins:
|
|
22
|
+
|
|
23
|
+
```rb
|
|
24
|
+
# remote_url plugin
|
|
25
|
+
attacher.form_assign({ "image_remote_url" => "https://example.com/..." })
|
|
26
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
27
|
+
```
|
|
28
|
+
```rb
|
|
29
|
+
# data_uri plugin
|
|
30
|
+
attacher.form_assign({ "image_data_uri" => "data:image/jpeg;base64,..." })
|
|
31
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
32
|
+
```
|
|
33
|
+
```rb
|
|
34
|
+
# remove_attachment plugin
|
|
35
|
+
attacher.form_assign({ "remove_image" => "1" })
|
|
36
|
+
attacher.file #=> nil
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The return value is a hash with form params, with file param replaced with
|
|
40
|
+
cached file data, which can later be assigned again to the record.
|
|
41
|
+
|
|
42
|
+
```rb
|
|
43
|
+
attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
|
|
44
|
+
#=> { :image => '{"id":"...","storage":"...","metadata":"..."}', "title" => "...", "description" => "..." }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You can also have attached file data returned as the `<name>_data` attribute,
|
|
48
|
+
suitable for persisting.
|
|
49
|
+
|
|
50
|
+
```rb
|
|
51
|
+
attacher.form_assign({ "image" => image, ... }, result: :attributes)
|
|
52
|
+
#=> { :image_data => '{"id":"...","storage":"...","metadata":"..."}', "title" => "...", "description" => "..." }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
[form_assign]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/form_assign.rb
|
data/doc/plugins/included.md
CHANGED
|
@@ -1,18 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Included
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
The [`included`][included] plugin allows you to hook up to the `.included` hook
|
|
4
|
-
of the attachment module, and call additional methods on the model
|
|
6
|
+
of the attachment module, and call additional methods on the model that
|
|
5
7
|
includes it.
|
|
6
8
|
|
|
7
9
|
```rb
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
10
|
+
class ImageUploader < Shrine
|
|
11
|
+
plugin :included do |name|
|
|
12
|
+
# called when attachment module is included into a model
|
|
13
|
+
|
|
14
|
+
self #=> Photo (the model class)
|
|
15
|
+
name #=> :image
|
|
11
16
|
end
|
|
12
17
|
end
|
|
13
18
|
```
|
|
19
|
+
```rb
|
|
20
|
+
class Photo
|
|
21
|
+
include ImageUploader::Attachment(:image) # triggers the included block
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For example, you can use it to define additional methods on the model:
|
|
14
26
|
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
```rb
|
|
28
|
+
class ImageUploader < Shrine
|
|
29
|
+
plugin :included do |name|
|
|
30
|
+
define_method(:"#{name}_width") { send(name)&.width }
|
|
31
|
+
define_method(:"#{name}_height") { send(name)&.height }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
```
|
|
35
|
+
```rb
|
|
36
|
+
photo = Photo.new(image: file)
|
|
37
|
+
photo.image_width #=> 1200
|
|
38
|
+
photo.image_height #=> 800
|
|
39
|
+
```
|
|
17
40
|
|
|
18
|
-
[included]: /lib/shrine/plugins/included.rb
|
|
41
|
+
[included]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/included.rb
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Infer Extension
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
The [`infer_extension`][infer_extension] plugin allows deducing the appropriate
|
|
4
6
|
file extension for the upload location based on the MIME type of the file. This
|
|
@@ -9,21 +11,30 @@ extension might not be known.
|
|
|
9
11
|
plugin :infer_extension
|
|
10
12
|
```
|
|
11
13
|
|
|
14
|
+
By default an extension will only be inferred if needed to supply an otherwise
|
|
15
|
+
missing extension. But option `force: true` will normalize even an already
|
|
16
|
+
present extension to the extension inferred from MIME type. This could be used
|
|
17
|
+
to fix incorrect or malicious extensions on user-submitted files.
|
|
18
|
+
|
|
19
|
+
```rb
|
|
20
|
+
plugin :infer_extension, force: true
|
|
21
|
+
```
|
|
22
|
+
|
|
12
23
|
## Inferrers
|
|
13
24
|
|
|
14
|
-
By default
|
|
15
|
-
also choose a different inferrer:
|
|
25
|
+
By default, the [mini_mime] gem will be used for inferring the extension, but
|
|
26
|
+
you can also choose a different inferrer:
|
|
16
27
|
|
|
17
28
|
```rb
|
|
18
|
-
plugin :infer_extension, inferrer: :
|
|
29
|
+
plugin :infer_extension, inferrer: :mime_types
|
|
19
30
|
```
|
|
20
31
|
|
|
21
32
|
The following inferrers are accepted:
|
|
22
33
|
|
|
23
|
-
| Name | Description
|
|
24
|
-
| :------------ | :-----------
|
|
25
|
-
| `:
|
|
26
|
-
| `:
|
|
34
|
+
| Name | Description |
|
|
35
|
+
| :------------ | :----------- |
|
|
36
|
+
| `:mini_mime` | (Default). Uses the [mini_mime] gem to infer the appropriate extension from MIME type. |
|
|
37
|
+
| `:mime_types` | Uses the [mime-types] gem to infer the appropriate extension from MIME type. |
|
|
27
38
|
|
|
28
39
|
You can also define your own inferrer, with the possibility to call the
|
|
29
40
|
built-in inferrers:
|
|
@@ -31,7 +42,7 @@ built-in inferrers:
|
|
|
31
42
|
```rb
|
|
32
43
|
plugin :infer_extension, inferrer: -> (mime_type, inferrers) do
|
|
33
44
|
# don't add extension if the file is a text file
|
|
34
|
-
inferrers[:
|
|
45
|
+
inferrers[:mini_mime].call(mime_type) unless mime_type == "text/plain"
|
|
35
46
|
end
|
|
36
47
|
```
|
|
37
48
|
|
|
@@ -89,6 +100,6 @@ Or disable logging altogether:
|
|
|
89
100
|
plugin :infer_extension, log_subscriber: nil
|
|
90
101
|
```
|
|
91
102
|
|
|
92
|
-
[infer_extension]: /lib/shrine/plugins/infer_extension.rb
|
|
103
|
+
[infer_extension]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/infer_extension.rb
|
|
93
104
|
[mime-types]: https://github.com/mime-types/ruby-mime-types
|
|
94
105
|
[mini_mime]: https://github.com/discourse/mini_mime
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Instrumentation
|
|
3
|
+
---
|
|
2
4
|
|
|
3
|
-
The [`instrumentation`][instrumentation] plugin
|
|
4
|
-
operations to a centralized notification component. In addition to that it
|
|
5
|
+
The [`instrumentation`][instrumentation] plugin publishes events for various
|
|
6
|
+
operations to a centralized notification component. In addition to that, it
|
|
5
7
|
provides default logging for these events.
|
|
6
8
|
|
|
7
9
|
```rb
|
|
@@ -40,6 +42,13 @@ Download (1002ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1
|
|
|
40
42
|
Delete (700ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :uploader=>Shrine}
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
It uses `Shrine.logger` for logging, which allows you to change where and how
|
|
46
|
+
are the logs going to be written:
|
|
47
|
+
|
|
48
|
+
```rb
|
|
49
|
+
Shrine.logger = Rails.logger # in Rails apps
|
|
50
|
+
```
|
|
51
|
+
|
|
43
52
|
You can choose to log only certain events, e.g. we can exclude metadata
|
|
44
53
|
extraction:
|
|
45
54
|
|
|
@@ -79,6 +88,7 @@ The following events are instrumented by the `instrumentation` plugin:
|
|
|
79
88
|
|
|
80
89
|
* [`upload.shrine`](#uploadshrine)
|
|
81
90
|
* [`download.shrine`](#downloadshrine)
|
|
91
|
+
* [`open.shrine`](#openshrine)
|
|
82
92
|
* [`exists.shrine`](#existsshrine)
|
|
83
93
|
* [`delete.shrine`](#deleteshrine)
|
|
84
94
|
* [`metadata.shrine`](#metadatashrine)
|
|
@@ -94,21 +104,33 @@ following payload:
|
|
|
94
104
|
| `:location` | The location of the uploaded file |
|
|
95
105
|
| `:io` | The uploaded IO object |
|
|
96
106
|
| `:upload_options` | Any upload options that were specified |
|
|
97
|
-
| `:
|
|
107
|
+
| `:metadata` | Metadata extracted during upload |
|
|
108
|
+
| `:options` | Any additional uploader options |
|
|
98
109
|
| `:uploader` | The uploader class that sent the event |
|
|
99
110
|
|
|
100
111
|
### download.shrine
|
|
101
112
|
|
|
102
|
-
The `download.shrine` event is logged on `UploadedFile#
|
|
103
|
-
`UploadedFile#download` and
|
|
104
|
-
contains the following payload:
|
|
113
|
+
The `download.shrine` event is logged on `UploadedFile#stream` (which includes
|
|
114
|
+
`UploadedFile#download`), and contains the following payload:
|
|
105
115
|
|
|
106
|
-
| Key
|
|
107
|
-
| :--
|
|
108
|
-
| `:storage`
|
|
109
|
-
| `:location`
|
|
110
|
-
| `:download_options` | Any
|
|
111
|
-
| `:uploader`
|
|
116
|
+
| Key | Description |
|
|
117
|
+
| :-- | :---- |
|
|
118
|
+
| `:storage` | The storage identifier |
|
|
119
|
+
| `:location` | The location of the uploaded file |
|
|
120
|
+
| `:download_options` | Any download options that were specified |
|
|
121
|
+
| `:uploader` | The uploader class that sent the event |
|
|
122
|
+
|
|
123
|
+
### open.shrine
|
|
124
|
+
|
|
125
|
+
The `download.shrine` event is logged on `UploadedFile#open` or when uploaded
|
|
126
|
+
file is implicitly opened on calling an IO method.
|
|
127
|
+
|
|
128
|
+
| Key | Description |
|
|
129
|
+
| :-- | :---- |
|
|
130
|
+
| `:storage` | The storage identifier |
|
|
131
|
+
| `:location` | The location of the uploaded file |
|
|
132
|
+
| `:download_options` | Any download options that were specified |
|
|
133
|
+
| `:uploader` | The uploader class that sent the event |
|
|
112
134
|
|
|
113
135
|
### exists.shrine
|
|
114
136
|
|
|
@@ -141,7 +163,7 @@ following payload:
|
|
|
141
163
|
| :-- | :---- |
|
|
142
164
|
| `:storage` | The storage identifier |
|
|
143
165
|
| `:io` | The uploaded IO object |
|
|
144
|
-
| `:options` |
|
|
166
|
+
| `:options` | Any options sent to the uploader |
|
|
145
167
|
| `:uploader` | The uploader class that sent the event |
|
|
146
168
|
|
|
147
169
|
## API
|
|
@@ -151,7 +173,7 @@ methods:
|
|
|
151
173
|
|
|
152
174
|
```rb
|
|
153
175
|
# sends a `my_event.shrine` event to the notifications component
|
|
154
|
-
Shrine.instrument(:my_event, foo: "bar") do
|
|
176
|
+
Shrine.instrument(:my_event, { foo: "bar" }) do
|
|
155
177
|
# do work
|
|
156
178
|
end
|
|
157
179
|
```
|
|
@@ -165,6 +187,6 @@ Shrine.subscribe(:my_event) do |event|
|
|
|
165
187
|
end
|
|
166
188
|
```
|
|
167
189
|
|
|
168
|
-
[instrumentation]: /lib/shrine/plugins/instrumentation.rb
|
|
190
|
+
[instrumentation]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/instrumentation.rb
|
|
169
191
|
[ActiveSupport::Notifications]: https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html
|
|
170
192
|
[dry-monitor]: https://github.com/dry-rb/dry-monitor
|