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
data/doc/attacher.md
CHANGED
|
@@ -1,283 +1,434 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Using Attacher
|
|
3
|
+
---
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
This guide explains what is `Shrine::Attacher` and how to use it.
|
|
6
|
+
|
|
7
|
+
## Introduction
|
|
8
|
+
|
|
9
|
+
The attachment logic is handled by a `Shrine::Attacher` object. The
|
|
10
|
+
`Shrine::Attachment` module simply provides a convenience layer around a
|
|
11
|
+
`Shrine::Attacher` object, which can be accessed via the `#<name>_attacher`
|
|
12
|
+
attribute.
|
|
7
13
|
|
|
8
14
|
```rb
|
|
9
|
-
class Photo
|
|
10
|
-
include ImageUploader::Attachment
|
|
15
|
+
class Photo
|
|
16
|
+
include ImageUploader::Attachment(:image)
|
|
11
17
|
end
|
|
12
18
|
```
|
|
19
|
+
```rb
|
|
20
|
+
photo = Photo.new
|
|
21
|
+
photo.image_attacher #=> #<ImageUploader::Attacher>
|
|
22
|
+
```
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
explicitness, or you need more control, you can achieve the same behaviour
|
|
16
|
-
using the `Shrine::Attacher` object, which is what the attachment interface
|
|
17
|
-
uses under the hood.
|
|
24
|
+
We can also instantiate the same `Shrine::Attacher` object directly:
|
|
18
25
|
|
|
19
26
|
```rb
|
|
20
|
-
attacher = ImageUploader::Attacher.
|
|
21
|
-
attacher.
|
|
22
|
-
attacher.
|
|
27
|
+
attacher = ImageUploader::Attacher.from_model(photo, :image)
|
|
28
|
+
attacher.file # called by `photo.image`
|
|
29
|
+
attacher.url # called by `photo.image_url`
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
The
|
|
26
|
-
|
|
32
|
+
The [`model`][model], [`entity`][entity], and [`column`][column] plugins
|
|
33
|
+
provide additional `Shrine::Attacher` methods (such as
|
|
34
|
+
`Shrine::Attacher.from_model` we see above), but in this guide we'll focus only
|
|
35
|
+
on the core `Shrine::Attacher` methods.
|
|
36
|
+
|
|
37
|
+
So, we'll assume a `Shrine::Attacher` object not backed by any model/entity:
|
|
27
38
|
|
|
28
39
|
```rb
|
|
29
|
-
attacher
|
|
40
|
+
attacher = Shrine::Attacher.new
|
|
30
41
|
```
|
|
31
42
|
|
|
32
|
-
##
|
|
43
|
+
## Storage
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
By default, an `Attacher` will use the `:cache` storage as the **temporary**
|
|
46
|
+
storage, and the `:store` storage as the **permanent** storage.
|
|
35
47
|
|
|
36
48
|
```rb
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
Shrine.storages = {
|
|
50
|
+
cache: Shrine::Storage::Memory.new,
|
|
51
|
+
store: Shrine::Storage::Memory.new,
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
```rb
|
|
55
|
+
attacher = Shrine::Attacher.new
|
|
56
|
+
attacher.cache_key #=> :cache
|
|
57
|
+
attacher.store_key #=> :store
|
|
41
58
|
```
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
also tell it to use different temporary and permanent storage:
|
|
60
|
+
We can also change the default storage:
|
|
45
61
|
|
|
46
62
|
```rb
|
|
47
|
-
|
|
63
|
+
attacher = Shrine::Attacher.new(cache: :other_cache, store: :other_store)
|
|
64
|
+
attacher.cache_key #=> :other_cache
|
|
65
|
+
attacher.store_key #=> :other_store
|
|
66
|
+
```
|
|
48
67
|
|
|
49
|
-
|
|
68
|
+
You can also change default attacher options on the `Shrine::Attachment`
|
|
69
|
+
module:
|
|
50
70
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
```rb
|
|
72
|
+
class Photo
|
|
73
|
+
include ImageUploader::Attachment(:image, cache: :other_cache, store: :other_store)
|
|
74
|
+
end
|
|
54
75
|
```
|
|
55
76
|
|
|
56
|
-
|
|
77
|
+
The `Attacher#cache` and `Attacher#store` methods will retrieve corresponding
|
|
78
|
+
uploaders:
|
|
57
79
|
|
|
58
80
|
```rb
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
81
|
+
attacher.cache #=> #<MyUploader @storage_key=:cache>
|
|
82
|
+
attacher.store #=> #<MyUploader @storage_key=:store>
|
|
62
83
|
```
|
|
63
84
|
|
|
64
|
-
|
|
65
|
-
for more details.
|
|
85
|
+
## Attaching
|
|
66
86
|
|
|
67
|
-
|
|
87
|
+
### Attaching cached
|
|
68
88
|
|
|
69
|
-
|
|
70
|
-
cached file in form of a JSON string, and assigns the cached result to record's
|
|
71
|
-
`<attachment>_data` attribute.
|
|
89
|
+
For attaching files submitted via a web form, `Attacher#assign` can be used:
|
|
72
90
|
|
|
73
91
|
```rb
|
|
74
|
-
|
|
75
|
-
|
|
92
|
+
attacher.assign(file)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If given a raw file, it will upload it to temporary storage:
|
|
76
96
|
|
|
77
|
-
|
|
78
|
-
attacher.assign(
|
|
97
|
+
```rb
|
|
98
|
+
attacher.assign(file)
|
|
99
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:cache ...>
|
|
79
100
|
```
|
|
80
101
|
|
|
81
|
-
|
|
82
|
-
forwarded to `Shrine#upload`. This allows you to do things like overriding
|
|
83
|
-
metadata, setting upload location, or passing upload options:
|
|
102
|
+
If given cached file data (JSON or Hash), it will set the cached file:
|
|
84
103
|
|
|
85
104
|
```rb
|
|
86
|
-
attacher.assign
|
|
87
|
-
|
|
88
|
-
location: "custom/location",
|
|
89
|
-
upload_options: { acl: "public-read" }
|
|
105
|
+
attacher.assign('{"id":"asdf.jpg","storage":"cache","metadata":{...}}')
|
|
106
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:cache ...>
|
|
90
107
|
```
|
|
91
108
|
|
|
92
|
-
If
|
|
93
|
-
assignment, you can do it like so:
|
|
109
|
+
If given an empty string, it will no-op:
|
|
94
110
|
|
|
95
111
|
```rb
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
attacher.assign("") # no-op
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If given `nil`, it will clear the attached file:
|
|
98
116
|
|
|
99
|
-
|
|
117
|
+
```rb
|
|
118
|
+
attacher.file #=> <Shrine::UploadedFile>
|
|
119
|
+
attacher.assign(nil)
|
|
120
|
+
attacher.file #=> nil
|
|
100
121
|
```
|
|
101
122
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
to permanent storage:
|
|
123
|
+
This plays nicely with the recommended HTML form fields for the attachment. If
|
|
124
|
+
you're not using the `hidden` form field (and therefore don't need empty
|
|
125
|
+
strings to be handled), you can also use `Attacher#attach_cached`:
|
|
106
126
|
|
|
107
127
|
```rb
|
|
108
|
-
|
|
109
|
-
attacher.
|
|
128
|
+
# uploads file to cache
|
|
129
|
+
attacher.attach_cached(file)
|
|
130
|
+
|
|
131
|
+
# sets cached file
|
|
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: { ... } })
|
|
135
|
+
|
|
136
|
+
# unsets attached file
|
|
137
|
+
attacher.attach_cached(nil)
|
|
110
138
|
```
|
|
111
139
|
|
|
112
|
-
|
|
140
|
+
### Attaching stored
|
|
113
141
|
|
|
114
|
-
The
|
|
115
|
-
a `Shrine::UploadedFile` object from it.
|
|
142
|
+
The `Attacher#attach` method uploads a given file to permanent storage:
|
|
116
143
|
|
|
117
144
|
```rb
|
|
118
|
-
attacher.
|
|
145
|
+
attacher.attach(file)
|
|
146
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:store ...>
|
|
119
147
|
```
|
|
120
148
|
|
|
121
|
-
|
|
122
|
-
|
|
149
|
+
This method is useful when attaching files from scripts, where validation
|
|
150
|
+
doesn't need to be performed, and where temporary storage can be skipped.
|
|
151
|
+
|
|
152
|
+
You can specify a different destination storage with the `:storage` option:
|
|
123
153
|
|
|
124
154
|
```rb
|
|
125
|
-
attacher.
|
|
155
|
+
attacher.attach(file, storage: :other_store)
|
|
156
|
+
attacher.file #=> #<Shrine::UploadedFile id="asdf.jpg" storage=:other_store ...>
|
|
126
157
|
```
|
|
127
158
|
|
|
128
|
-
|
|
129
|
-
|
|
159
|
+
Any additional options passed to `Attacher#attach`, `Attacher#attach_cached`
|
|
160
|
+
and `Attacher#assign` are forwarded to the uploader:
|
|
130
161
|
|
|
131
162
|
```rb
|
|
132
|
-
|
|
133
|
-
attacher.
|
|
163
|
+
attacher.attach(file, metadata: { "foo" => "bar" }) # adding metadata
|
|
164
|
+
attacher.attach(file, upload_options: { acl: "private" }) # setting upload options
|
|
165
|
+
attacher.attach(file, location: "path/to/file") # setting upload location
|
|
134
166
|
```
|
|
135
167
|
|
|
136
|
-
|
|
168
|
+
### Uploading
|
|
137
169
|
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
If you want to upload a file to without attaching it, you can use
|
|
171
|
+
`Attacher#upload`:
|
|
140
172
|
|
|
141
173
|
```rb
|
|
142
|
-
attacher.
|
|
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 ...>
|
|
143
177
|
```
|
|
144
178
|
|
|
145
|
-
|
|
179
|
+
This is useful if you want to attacher [context](#context) such as `:record`
|
|
180
|
+
and `:name` to be automatically passed to the uploader.
|
|
146
181
|
|
|
147
|
-
You can
|
|
148
|
-
stored.
|
|
182
|
+
You can also pass additional options for `Shrine#upload`:
|
|
149
183
|
|
|
150
184
|
```rb
|
|
151
|
-
attacher.
|
|
152
|
-
attacher.
|
|
185
|
+
attacher.upload(file, metadata: { "foo" => "bar" }) # adding metadata
|
|
186
|
+
attacher.upload(file, upload_options: { acl: "private" }) # setting upload options
|
|
187
|
+
attacher.upload(file, location: "path/to/file") # setting upload location
|
|
153
188
|
```
|
|
154
189
|
|
|
155
|
-
|
|
190
|
+
### Changes
|
|
156
191
|
|
|
157
|
-
|
|
158
|
-
|
|
192
|
+
When a new file is attached, calling [`Attacher#finalize`](#finalization) will
|
|
193
|
+
perform additional actions such as promotion and deleting any previous file.
|
|
194
|
+
It will also trigger [validation].
|
|
195
|
+
|
|
196
|
+
You can check whether a new file has been attached with `Attacher#changed?`:
|
|
159
197
|
|
|
160
198
|
```rb
|
|
161
|
-
attacher.
|
|
162
|
-
attacher.errors #=> ["is larger than 10 MB"]
|
|
199
|
+
attacher.changed? #=> true
|
|
163
200
|
```
|
|
164
201
|
|
|
165
|
-
|
|
202
|
+
You can use `Attacher#change` to attach an `UploadedFile` object as is:
|
|
166
203
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
204
|
+
```rb
|
|
205
|
+
uploaded_file #=> #<Shrine::UploadedFile id="foo" ...>
|
|
206
|
+
attacher.change(uploaded_file)
|
|
207
|
+
attacher.file #=> #<Shrine::UploadedFile id="foo" ...>
|
|
208
|
+
attacher.changed? #=> true
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
If you want to attach a file without triggering dirty tracking or validation,
|
|
212
|
+
you can use `Attacher#set`:
|
|
213
|
+
|
|
214
|
+
```rb
|
|
215
|
+
uploaded_file #=> #<Shrine::UploadedFile id="foo" ...>
|
|
216
|
+
attacher.set(uploaded_file)
|
|
217
|
+
attacher.file #=> #<Shrine::UploadedFile id="foo" ...>
|
|
218
|
+
attacher.changed? #=> false
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Finalizing
|
|
222
|
+
|
|
223
|
+
After the file is attached (with `Attacher#assign`, `Attacher#attach_cached`,
|
|
224
|
+
or `Attacher#attach`), and data has been validated, the attachment can be
|
|
225
|
+
"finalized":
|
|
170
226
|
|
|
171
227
|
```rb
|
|
172
|
-
# Replaces previous attachment and replaces new
|
|
173
228
|
attacher.finalize
|
|
174
229
|
```
|
|
175
230
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
`Shrine::UploadedFile` to permanent storage, and swaps it with the current
|
|
179
|
-
attachment, unless a new file was attached in the meanwhile.
|
|
231
|
+
The `Attacher#finalize` method performs [promoting](#promoting) and
|
|
232
|
+
[replacing](#replacing). It also clears dirty tracking:
|
|
180
233
|
|
|
181
234
|
```rb
|
|
182
|
-
|
|
183
|
-
attacher.
|
|
235
|
+
attacher.changed? #=> true
|
|
236
|
+
attacher.finalize
|
|
237
|
+
attacher.changed? #=> false
|
|
184
238
|
```
|
|
185
239
|
|
|
186
|
-
|
|
187
|
-
|
|
240
|
+
### Promoting
|
|
241
|
+
|
|
242
|
+
`Attacher#finalize` checks if the attached file has been uploaded to temporary
|
|
243
|
+
storage, and in this case uploads it to permanent storage.
|
|
244
|
+
|
|
245
|
+
```rb
|
|
246
|
+
attacher.attach_cached(io)
|
|
247
|
+
attacher.finalize # uploads attached file to permanent storage
|
|
248
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:store ...>
|
|
249
|
+
```
|
|
188
250
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
things like override metadata, set upload location, or pass upload options:
|
|
251
|
+
Internally it calls `Attacher#promote_cached`, which you can call directly if
|
|
252
|
+
you want to pass any promote options:
|
|
192
253
|
|
|
193
254
|
```rb
|
|
194
|
-
attacher.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
upload_options: { acl: "public-read" }
|
|
255
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:cache ...>
|
|
256
|
+
attacher.promote_cached # uploads attached file to permanent storage if new and cached
|
|
257
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:store ...>
|
|
198
258
|
```
|
|
199
259
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
hasn't changed (if the `backgrounding` plugin is loaded).
|
|
260
|
+
You can also call `Attacher#promote` if you want to upload attached file to
|
|
261
|
+
permanent storage, regardless of whether it's cached or newly attached:
|
|
203
262
|
|
|
204
263
|
```rb
|
|
205
|
-
attacher.
|
|
264
|
+
attacher.promote
|
|
206
265
|
```
|
|
207
266
|
|
|
208
|
-
|
|
267
|
+
Any options passed to `Attacher#promote_cached` or `Attacher#promote` will be
|
|
268
|
+
forwarded to `Shrine#upload`.
|
|
209
269
|
|
|
210
|
-
|
|
270
|
+
### Replacing
|
|
211
271
|
|
|
212
|
-
|
|
213
|
-
files in the background, and the corresponding methods are prefixed with `_`:
|
|
272
|
+
`Attacher#finalize` also deletes the previous attached file if any:
|
|
214
273
|
|
|
215
274
|
```rb
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
275
|
+
previous_file = attacher.file
|
|
276
|
+
|
|
277
|
+
attacher.attach(io)
|
|
278
|
+
attacher.finalize
|
|
279
|
+
|
|
280
|
+
previous_file.exists? #=> false
|
|
219
281
|
```
|
|
282
|
+
|
|
283
|
+
Internally it calls `Attacher#destroy_previous` to do this:
|
|
284
|
+
|
|
220
285
|
```rb
|
|
221
|
-
attacher.
|
|
222
|
-
attacher._delete(uploaded_file) # calls the registered `Attacher.delete` block
|
|
286
|
+
attacher.destroy_previous
|
|
223
287
|
```
|
|
224
288
|
|
|
225
|
-
|
|
289
|
+
## Retrieving
|
|
226
290
|
|
|
227
|
-
|
|
291
|
+
### File
|
|
292
|
+
|
|
293
|
+
The `Attacher#file` is used to retrieve the attached file:
|
|
294
|
+
|
|
295
|
+
```rb
|
|
296
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
297
|
+
```
|
|
228
298
|
|
|
229
|
-
|
|
230
|
-
default it will hold `:record` and `:name`:
|
|
299
|
+
If no file is attached, `Attacher#file` returns nil:
|
|
231
300
|
|
|
232
301
|
```rb
|
|
233
|
-
attacher.
|
|
302
|
+
attacher.file #=> nil
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
If you want to assert a file is attached, you can use `Attacher#file!`:
|
|
306
|
+
|
|
307
|
+
```rb
|
|
308
|
+
attacher.file! #~> Shrine::Error: no file is attached
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Attached
|
|
312
|
+
|
|
313
|
+
You can also check whether a file is attached with `Attacher#attached?`:
|
|
314
|
+
|
|
315
|
+
```rb
|
|
316
|
+
attacher.attached? # returns whether file is attached
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
If you want to check to which storage a file is uploaded to, you can use
|
|
320
|
+
`Attacher#cached?` and `Attacher#stored?`:
|
|
321
|
+
|
|
322
|
+
```rb
|
|
323
|
+
attacher.attach(io)
|
|
324
|
+
attacher.stored? #=> true (checks current file)
|
|
325
|
+
attacher.stored?(attacher.file) #=> true (checks given file)
|
|
326
|
+
```
|
|
327
|
+
```rb
|
|
328
|
+
attacher.attach_cached(io)
|
|
329
|
+
attacher.cached? #=> true (checks current file)
|
|
330
|
+
attacher.cached?(attacher.file) #=> true (checks given file)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### URL
|
|
334
|
+
|
|
335
|
+
The attached file URL can be retrieved with `Attacher#url`:
|
|
336
|
+
|
|
337
|
+
```rb
|
|
338
|
+
attacher.url #=> "https://example.com/file.jpg"
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
If no file is attached, `Attacher#url` returns `nil`:
|
|
342
|
+
|
|
343
|
+
```rb
|
|
344
|
+
attacher.url #=> nil
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Data
|
|
348
|
+
|
|
349
|
+
You can retrieve plain attached file data with `Attacher#data`:
|
|
350
|
+
|
|
351
|
+
```rb
|
|
352
|
+
attacher.data #=>
|
|
234
353
|
# {
|
|
235
|
-
#
|
|
236
|
-
#
|
|
354
|
+
# "id" => "abc123.jpg",
|
|
355
|
+
# "storage" => "store",
|
|
356
|
+
# "metadata" => {
|
|
357
|
+
# "size" => 223984,
|
|
358
|
+
# "filename" => "nature.jpg",
|
|
359
|
+
# "mime_type" => "image/jpeg",
|
|
360
|
+
# }
|
|
237
361
|
# }
|
|
238
362
|
```
|
|
239
363
|
|
|
240
|
-
|
|
241
|
-
|
|
364
|
+
This data can be stored somewhere, and later the attached file can be loaded
|
|
365
|
+
from it:
|
|
242
366
|
|
|
243
367
|
```rb
|
|
244
|
-
|
|
368
|
+
# new attacher
|
|
369
|
+
attacher = Shrine::Attacher.from_data(data)
|
|
370
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
371
|
+
|
|
372
|
+
# existing attacher
|
|
373
|
+
attacher.file #=> nil
|
|
374
|
+
attacher.load_data(data)
|
|
375
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Internally `Attacher#uploaded_file` is used to convert uploaded file data into
|
|
379
|
+
a `Shrine::UploadedFile` object:
|
|
380
|
+
|
|
381
|
+
```rb
|
|
382
|
+
attacher.uploaded_file("id" => "...", "storage" => "...", "metadata" => { ... }) #=> #<Shrine::UploadedFile>
|
|
383
|
+
attacher.uploaded_file(id: "...", storage: "...", metadata: { ... }) #=> #<Shrine::UploadedFile>
|
|
384
|
+
attacher.uploaded_file('{"id":"...","storage":"...","metadata":{...}}') #=> #<Shrine::UploadedFile>
|
|
245
385
|
```
|
|
246
386
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
387
|
+
You will likely want to use a higher level abstraction for saving and loading
|
|
388
|
+
this data, see [`column`][column], [`entity`][entity] and [`model`][model]
|
|
389
|
+
plugins for more details.
|
|
250
390
|
|
|
251
|
-
##
|
|
391
|
+
## Deleting
|
|
252
392
|
|
|
253
|
-
|
|
393
|
+
The attached file can be deleted via `Attacher#destroy_attached`:
|
|
254
394
|
|
|
255
395
|
```rb
|
|
256
|
-
|
|
257
|
-
uploaded_file = uploader.upload(image) # uploads the file to `:store` storage
|
|
258
|
-
uploader.delete(uploaded_file) # deletes the uploaded file from `:store`
|
|
396
|
+
attacher.destroy_attached
|
|
259
397
|
```
|
|
260
398
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
399
|
+
This will not delete cached files, to not interrupt any potential
|
|
400
|
+
[backgrounding] that might be in process.
|
|
401
|
+
|
|
402
|
+
If you want to delete the attached file regardless of storage it's uploaded to,
|
|
403
|
+
you can use `Attacher#destroy`:
|
|
264
404
|
|
|
265
405
|
```rb
|
|
266
|
-
attacher.
|
|
267
|
-
# => #<Shrine::UploadedFile: @data={"storage" => "cache", ...}>
|
|
268
|
-
attacher.store!(file) # uploads file to permanent storage
|
|
269
|
-
# => #<Shrine::UploadedFile: @data={"storage" => "store", ...}>
|
|
270
|
-
attacher.delete!(uploaded_file) # deletes uploaded file from storage
|
|
406
|
+
attacher.destroy
|
|
271
407
|
```
|
|
272
408
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
`
|
|
409
|
+
## Context
|
|
410
|
+
|
|
411
|
+
The `Attacher#context` hash is automatically forwarded to the uploader on
|
|
412
|
+
`Attacher#upload`. When [`model`][model] or [`entity`][model] plugin is loaded,
|
|
413
|
+
this will include `:record` and `:name` values:
|
|
276
414
|
|
|
277
415
|
```rb
|
|
278
|
-
attacher.
|
|
279
|
-
attacher.
|
|
280
|
-
attacher.delete!(uploaded_file, foo: "bar")
|
|
416
|
+
attacher = Shrine::Attacher.from_model(photo, :image)
|
|
417
|
+
attacher.context #=> { record: #<Photo>, name: :image }
|
|
281
418
|
```
|
|
282
419
|
|
|
283
|
-
|
|
420
|
+
You can add here any other parameters you want to forward to the uploader:
|
|
421
|
+
|
|
422
|
+
```rb
|
|
423
|
+
attacher.context[:foo] = "bar"
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
However, it's generally better practice to pass uploader options directly to
|
|
427
|
+
`Attacher#assign`, `Attacher#attach`, `Attacher#promote` or any other method
|
|
428
|
+
that's calling `Attacher#upload`.
|
|
429
|
+
|
|
430
|
+
[validation]: https://shrinerb.com/docs/plugins/validation
|
|
431
|
+
[column]: https://shrinerb.com/docs/plugins/column
|
|
432
|
+
[entity]: https://shrinerb.com/docs/plugins/entity
|
|
433
|
+
[model]: https://shrinerb.com/docs/plugins/model
|
|
434
|
+
[backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
|