shrine 2.19.4 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +485 -43
- data/LICENSE.txt +1 -1
- data/README.md +81 -977
- 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 +102 -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 +1115 -0
- data/doc/metadata.md +190 -109
- data/doc/multiple_files.md +62 -34
- 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 +162 -101
- data/doc/plugins/derivatives.md +829 -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 +14 -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 +185 -167
- 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 +4 -0
- 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/retrieving_uploads.md +4 -1
- 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 +117 -83
- data/doc/testing.md +124 -144
- data/doc/upgrading_to_3.md +710 -0
- data/doc/validation.md +54 -90
- data/lib/shrine/attacher.rb +287 -171
- 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 +89 -134
- data/lib/shrine/plugins/derivatives.rb +637 -0
- data/lib/shrine/plugins/determine_mime_type.rb +9 -21
- data/lib/shrine/plugins/download_endpoint.rb +109 -133
- data/lib/shrine/plugins/dynamic_storage.rb +5 -11
- data/lib/shrine/plugins/entity.rb +152 -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 +13 -20
- data/lib/shrine/plugins/instrumentation.rb +54 -42
- 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 +158 -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 +18 -22
- 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 +15 -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 +10 -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 +25 -23
- 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 +34 -57
- 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 +154 -158
- data/lib/shrine/uploaded_file.rb +28 -30
- data/lib/shrine/version.rb +3 -3
- data/lib/shrine.rb +86 -149
- data/shrine.gemspec +9 -10
- metadata +79 -83
- 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
|