shrine 3.0.0 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +87 -33
- data/LICENSE.txt +1 -1
- data/README.md +94 -4
- data/doc/advantages.md +35 -18
- data/doc/attacher.md +16 -17
- data/doc/carrierwave.md +75 -34
- data/doc/changing_derivatives.md +39 -39
- data/doc/design.md +134 -85
- data/doc/external/articles.md +56 -41
- data/doc/external/extensions.md +38 -34
- data/doc/getting_started.md +182 -112
- data/doc/metadata.md +79 -43
- data/doc/multiple_files.md +5 -3
- data/doc/paperclip.md +110 -42
- data/doc/plugins/activerecord.md +5 -5
- data/doc/plugins/add_metadata.md +92 -35
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +205 -169
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/entity.md +3 -3
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +2 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +21 -10
- data/doc/plugins/model.md +4 -4
- data/doc/plugins/persistence.md +1 -0
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +8 -3
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/sequel.md +4 -4
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +2 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +2 -2
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/plugins/versions.md +11 -11
- data/doc/processing.md +289 -125
- data/doc/refile.md +39 -18
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/3.0.0.md +275 -258
- data/doc/release_notes/3.0.1.md +22 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +32 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/securing_uploads.md +3 -3
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +105 -86
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +115 -33
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +8 -8
- data/lib/shrine/attacher.rb +19 -14
- data/lib/shrine/attachment.rb +5 -5
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/add_metadata.rb +12 -3
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +10 -6
- data/lib/shrine/plugins/derivatives.rb +19 -17
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/entity.rb +6 -6
- data/lib/shrine/plugins/metadata_attributes.rb +1 -1
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +2 -2
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +18 -9
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +3 -3
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/s3.rb +62 -38
- data/lib/shrine/uploaded_file.rb +5 -1
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +6 -7
- metadata +23 -29
data/doc/changing_derivatives.md
CHANGED
@@ -42,7 +42,7 @@ gem "image_processing", "~> 1.8"
|
|
42
42
|
require "image_processing/mini_magick"
|
43
43
|
|
44
44
|
class ImageUploader < Shrine
|
45
|
-
Attacher.
|
45
|
+
Attacher.derivatives do |original|
|
46
46
|
magick = ImageProcessing::MiniMagick.source(original)
|
47
47
|
|
48
48
|
# generate the thumbnails you want here
|
@@ -93,16 +93,16 @@ now you want to reprocess them for existing attachments.*
|
|
93
93
|
Let's assume we've made the following change and have deployed it to production:
|
94
94
|
|
95
95
|
```diff
|
96
|
-
Attacher.
|
97
|
-
|
96
|
+
Attacher.derivatives do |original|
|
97
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
98
98
|
+ .saver(quality: 85)
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
{
|
101
|
+
small: magick.resize_to_limit!(300, 300),
|
102
|
+
medium: magick.resize_to_limit!(500, 500),
|
103
|
+
large: magick.resize_to_limit!(800, 800),
|
104
|
+
}
|
105
|
+
end
|
106
106
|
```
|
107
107
|
|
108
108
|
We can now run the following script to reprocess derivatives for all existing
|
@@ -139,16 +139,16 @@ you want to reprocess them for existing attachments.*
|
|
139
139
|
Let's assume we've made a following change and have deployed it to production:
|
140
140
|
|
141
141
|
```diff
|
142
|
-
Attacher.
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
-
|
148
|
-
+
|
149
|
-
|
150
|
-
|
151
|
-
end
|
142
|
+
Attacher.derivatives do |original|
|
143
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
144
|
+
|
145
|
+
{
|
146
|
+
small: magick.resize_to_limit!(300, 300),
|
147
|
+
- medium: magick.resize_to_limit!(500, 500),
|
148
|
+
+ medium: magick.resize_to_limit!(600, 600),
|
149
|
+
large: magick.resize_to_limit!(800, 800),
|
150
|
+
}
|
151
|
+
end
|
152
152
|
```
|
153
153
|
|
154
154
|
We can now run the following script to reprocess the derivative for all
|
@@ -189,16 +189,16 @@ you want to add it to existing attachments.*
|
|
189
189
|
Let's assume we've made a following change and have deployed it to production:
|
190
190
|
|
191
191
|
```diff
|
192
|
-
Attacher.
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
+
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
192
|
+
Attacher.derivatives do |original|
|
193
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
194
|
+
|
195
|
+
{
|
196
|
+
+ square: magick.resize_to_fill!(150, 150),
|
197
|
+
small: magick.resize_to_limit!(300, 300),
|
198
|
+
medium: magick.resize_to_limit!(600, 600),
|
199
|
+
large: magick.resize_to_limit!(800, 800),
|
200
|
+
}
|
201
|
+
end
|
202
202
|
```
|
203
203
|
|
204
204
|
We can now run following script to add the new derivative for all existing
|
@@ -239,16 +239,16 @@ existing attachments.*
|
|
239
239
|
Let's assume we've made the following change and have deployed it to production:
|
240
240
|
|
241
241
|
```diff
|
242
|
-
Attacher.
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
242
|
+
Attacher.derivatives do |original|
|
243
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
244
|
+
|
245
|
+
{
|
246
|
+
- square: magick.resize_to_fill!(150, 150),
|
247
|
+
small: magick.resize_to_limit!(300, 300),
|
248
|
+
medium: magick.resize_to_limit!(600, 600),
|
249
|
+
large: magick.resize_to_limit!(800, 800),
|
250
|
+
}
|
251
|
+
end
|
252
252
|
```
|
253
253
|
|
254
254
|
We can now run following script to remove the unused derivative for all
|
data/doc/design.md
CHANGED
@@ -2,22 +2,25 @@
|
|
2
2
|
title: The Design of Shrine
|
3
3
|
---
|
4
4
|
|
5
|
-
*If you want an in-depth walkthrough through the Shrine codebase, see [Notes on
|
5
|
+
*If you want an in-depth walkthrough through the Shrine codebase, see [Notes on
|
6
|
+
study of shrine implementation] article by Jonathan Rochkind.*
|
6
7
|
|
7
|
-
There are five main types of
|
8
|
+
There are five main types of classes that you deal with in Shrine:
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
| Class | Description |
|
11
|
+
| :---- | :---------- |
|
12
|
+
| `Shrine::Storage::*` | Manages files on a particular storage service |
|
13
|
+
| `Shrine` | Wraps uploads and handles loading plugins |
|
14
|
+
| `Shrine::UploadedFile` | Represents a file uploaded to a storage |
|
15
|
+
| `Shrine::Attacher` | Handles file attachment logic |
|
16
|
+
| `Shrine::Attachment` | Provides convenience model attachment interface |
|
14
17
|
|
15
18
|
## Storage
|
16
19
|
|
17
20
|
On the lowest level we have a storage. A storage class encapsulates file
|
18
21
|
management logic on a particular service. It is what actually performs uploads,
|
19
22
|
generation of URLs, deletions and similar. By convention it is namespaced under
|
20
|
-
`Shrine::Storage
|
23
|
+
`Shrine::Storage::*`.
|
21
24
|
|
22
25
|
```rb
|
23
26
|
filesystem = Shrine::Storage::FileSystem.new("uploads")
|
@@ -26,7 +29,7 @@ filesystem.url("foo") #=> "uploads/foo"
|
|
26
29
|
filesystem.delete("foo")
|
27
30
|
```
|
28
31
|
|
29
|
-
A storage is a PORO which
|
32
|
+
A storage is a PORO which implements the following interface:
|
30
33
|
|
31
34
|
```rb
|
32
35
|
class Shrine
|
@@ -56,13 +59,14 @@ class Shrine
|
|
56
59
|
end
|
57
60
|
```
|
58
61
|
|
59
|
-
Storages are typically not used directly, but through `Shrine
|
62
|
+
Storages are typically not used directly, but through [`Shrine`](#shrine) and
|
63
|
+
[`Shrine::UploadedFile`](#shrine-uploadedfile) classes.
|
60
64
|
|
61
65
|
## `Shrine`
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
name:
|
67
|
+
The `Shrine` class (also called an "uploader") primarily provides a wrapper
|
68
|
+
method around `Storage#upload`. First, the storage needs to be registered under
|
69
|
+
a name:
|
66
70
|
|
67
71
|
```rb
|
68
72
|
Shrine.storages[:disk] = Shrine::Storage::FileSystem.new("uploads")
|
@@ -72,7 +76,7 @@ Now we can upload files to the registered storage:
|
|
72
76
|
|
73
77
|
```rb
|
74
78
|
uploaded_file = Shrine.upload(file, :disk)
|
75
|
-
uploaded_file #=> #<Shrine::UploadedFile
|
79
|
+
uploaded_file #=> #<Shrine::UploadedFile storage=:disk id="6a9fb596cc554efb" ...>
|
76
80
|
```
|
77
81
|
|
78
82
|
The argument to `Shrine#upload` must be an IO-like object. The method does the
|
@@ -84,63 +88,97 @@ following:
|
|
84
88
|
* closes the file
|
85
89
|
* creates a `Shrine::UploadedFile` from the data
|
86
90
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
plugin
|
91
|
+
### Plugins
|
92
|
+
|
93
|
+
The `Shrine` class is also used for loading plugins, which provide additional
|
94
|
+
functionality by extending core classes.
|
95
|
+
|
96
|
+
```rb
|
97
|
+
Shrine.plugin :derivatives
|
98
|
+
|
99
|
+
Shrine::UploadedFile.ancestors #=> [..., Shrine::Plugins::Derivatives::FileMethods, Shrine::UploadedFile::InstanceMethods, ...]
|
100
|
+
Shrine::Attacher.ancestors #=> [..., Shrine::Plugins::Derivatives::AttacherMethods, Shrine::Attacher::InstanceMethods, ...]
|
101
|
+
Shrine::Attachment.ancestors #=> [..., Shrine::Plugins::Derivatives::AttachmentMethods, Shrine::Attachment::InstanceMethods, ...]
|
102
|
+
```
|
103
|
+
|
104
|
+
The plugins store their configuration in `Shrine.opts`:
|
105
|
+
|
106
|
+
```rb
|
107
|
+
Shrine.plugin :derivation_endpoint, secret_key: "foo"
|
108
|
+
Shrine.plugin :default_storage, store: :other_store
|
109
|
+
Shrine.plugin :activerecord
|
110
|
+
|
111
|
+
Shrine.opts #=>
|
112
|
+
# { derivation_endpoint: { options: { secret_key: "foo" }, derivations: {} },
|
113
|
+
# default_storage: { store: :other_store },
|
114
|
+
# column: { serializer: Shrine::Plugins::Column::JsonSerializer },
|
115
|
+
# model: { cache: true },
|
116
|
+
# activerecord: { callbacks: true, validations: true } }
|
117
|
+
```
|
118
|
+
|
119
|
+
Each `Shrine` subclass has its own copy of the core classes, storages and
|
120
|
+
options, which makes it possible to customize attachment logic per uploader.
|
121
|
+
|
122
|
+
```rb
|
123
|
+
MyUploader = Class.new(Shrine)
|
124
|
+
MyUploader::UploadedFile.superclass #=> Shrine::UploadedFile
|
125
|
+
MyUploader::Attacher.superclass #=> Shrine::Attacher
|
126
|
+
MyUploader::Attachment.superclass #=> Shrine::Attachment
|
127
|
+
```
|
128
|
+
|
129
|
+
See [Creating a New Plugin] guide and the [Plugin system of Sequel and Roda]
|
130
|
+
article for more details on the design of Shrine's plugin system.
|
94
131
|
|
95
132
|
## `Shrine::UploadedFile`
|
96
133
|
|
97
|
-
`Shrine::UploadedFile` represents a file that was uploaded to a
|
98
|
-
|
99
|
-
|
134
|
+
A `Shrine::UploadedFile` object represents a file that was uploaded to a
|
135
|
+
storage, containing upload location, storage, and any metadata extracted during
|
136
|
+
the upload.
|
100
137
|
|
101
138
|
```rb
|
102
|
-
uploaded_file
|
103
|
-
|
139
|
+
uploaded_file #=> #<Shrine::UploadedFile id="949sdjg834.jpg" storage=:store metadata={...}>
|
140
|
+
|
141
|
+
uploaded_file.id #=> "949sdjg834.jpg"
|
142
|
+
uploaded_file.storage_key #=> :store
|
143
|
+
uploaded_file.storage #=> #<Shrine::Storage::S3>
|
144
|
+
uploaded_file.metadata #=> {...}
|
145
|
+
```
|
146
|
+
|
147
|
+
It has convenience methods for accessing metadata:
|
148
|
+
|
149
|
+
```rb
|
150
|
+
uploaded_file.metadata #=>
|
104
151
|
# {
|
105
|
-
# "
|
106
|
-
# "
|
107
|
-
# "
|
108
|
-
# "filename" => "resume.pdf",
|
109
|
-
# "mime_type" => "application/pdf",
|
110
|
-
# "size" => 983294,
|
111
|
-
# },
|
152
|
+
# "filename" => "matrix.mp4",
|
153
|
+
# "mime_type" => "video/mp4",
|
154
|
+
# "size" => 345993,
|
112
155
|
# }
|
156
|
+
|
157
|
+
uploaded_file.original_filename #=> "matrix.mp4"
|
158
|
+
uploaded_file.extension #=> "mp4"
|
159
|
+
uploaded_file.mime_type #=> "video/mp4"
|
160
|
+
uploaded_file.size #=> 345993
|
113
161
|
```
|
114
162
|
|
115
|
-
|
116
|
-
some metadata: original filename, MIME type and filesize. The
|
117
|
-
`Shrine::UploadedFile` object has handy methods which use this data:
|
163
|
+
It also has methods that delegate to the storage:
|
118
164
|
|
119
165
|
```rb
|
120
|
-
|
121
|
-
uploaded_file.
|
122
|
-
uploaded_file.
|
123
|
-
uploaded_file.
|
124
|
-
|
125
|
-
|
126
|
-
# storage methods
|
127
|
-
uploaded_file.url
|
128
|
-
uploaded_file.exists?
|
129
|
-
uploaded_file.open
|
130
|
-
uploaded_file.download
|
131
|
-
uploaded_file.delete
|
132
|
-
# ...
|
166
|
+
uploaded_file.url #=> "https://my-bucket.s3.amazonaws.com/949sdjg834.jpg"
|
167
|
+
uploaded_file.open { |io| ... } # opens the uploaded file stream
|
168
|
+
uploaded_file.download { |file| ... } # downloads the uploaded file to disk
|
169
|
+
uploaded_file.stream(destination) # streams uploaded content into a writable destination
|
170
|
+
uploaded_file.exists? #=> true
|
171
|
+
uploaded_file.delete # deletes the uploaded file from the storage
|
133
172
|
```
|
134
173
|
|
135
|
-
A `Shrine::UploadedFile` is itself an IO-like object (
|
136
|
-
|
174
|
+
A `Shrine::UploadedFile` is itself an IO-like object (built on top of
|
175
|
+
`Storage#open`), so it can be passed to `Shrine#upload` as well.
|
137
176
|
|
138
177
|
## `Shrine::Attacher`
|
139
178
|
|
140
179
|
We usually want to treat uploaded files as *attachments* to records, saving
|
141
|
-
their data into a database column. This is
|
142
|
-
|
143
|
-
`Shrine::UploadedFile` objects internally.
|
180
|
+
their data into a database column. This is done by `Shrine::Attacher`, which
|
181
|
+
internally uses `Shrine` and `Shrine::UploadedFile` classes.
|
144
182
|
|
145
183
|
The attaching process requires a temporary and a permanent storage to be
|
146
184
|
registered (by default that's `:cache` and `:store`):
|
@@ -152,40 +190,50 @@ Shrine.storages = {
|
|
152
190
|
}
|
153
191
|
```
|
154
192
|
|
155
|
-
A `Shrine::Attacher`
|
156
|
-
|
193
|
+
A `Shrine::Attacher` can be initialized standalone and handle the common
|
194
|
+
attachment flow, which includes dirty tracking (promoting cached file to
|
195
|
+
permanent storage, deleting previously attached file), validation, processing,
|
196
|
+
serialization etc.
|
197
|
+
|
198
|
+
```rb
|
199
|
+
attacher = Shrine::Attacher.new
|
200
|
+
|
201
|
+
# ... user uploads a file ...
|
202
|
+
|
203
|
+
attacher.assign(io) # uploads to temporary storage
|
204
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:cache ...>
|
205
|
+
|
206
|
+
# ... handle file validations ...
|
207
|
+
|
208
|
+
attacher.finalize # uploads to permanent storage
|
209
|
+
attacher.file #=> #<Shrine::UploadedFile storage=:store ...>
|
210
|
+
```
|
211
|
+
|
212
|
+
It can also be initialized with a model instance to handle serialization into a
|
213
|
+
model attribute:
|
157
214
|
|
158
215
|
```rb
|
159
216
|
attacher = Shrine::Attacher.from_model(photo, :image)
|
160
217
|
|
161
218
|
attacher.assign(file)
|
162
|
-
|
163
|
-
attacher.record.image_data #=> "{\"storage\":\"cache\",\"id\":\"9260ea09d8effd.jpg\",\"metadata\":{...}}"
|
219
|
+
photo.image_data #=> "{\"storage\":\"cache\",\"id\":\"9260ea09d8effd.jpg\",\"metadata\":{...}}"
|
164
220
|
|
165
221
|
attacher.finalize
|
166
|
-
|
167
|
-
attacher.record.image_data #=> "{\"storage\":\"store\",\"id\":\"ksdf02lr9sf3la.jpg\",\"metadata\":{...}}"
|
222
|
+
photo.image_data #=> "{\"storage\":\"store\",\"id\":\"ksdf02lr9sf3la.jpg\",\"metadata\":{...}}"
|
168
223
|
```
|
169
224
|
|
170
|
-
|
171
|
-
|
172
|
-
permanent storage. Behind the scenes a cached `Shrine::UploadedFile` is given
|
173
|
-
to `Shrine#upload`, which works because `Shrine::UploadedFile` is an IO-like
|
174
|
-
object. After both caching and promoting the data hash of the uploaded file is
|
175
|
-
assigned to the record's column as JSON.
|
176
|
-
|
177
|
-
For more details see [Using Attacher].
|
225
|
+
For more details, see the [Using Attacher] guide and
|
226
|
+
[`entity`][entity]/[`model`][model] plugins.
|
178
227
|
|
179
228
|
## `Shrine::Attachment`
|
180
229
|
|
181
|
-
`Shrine::Attachment`
|
182
|
-
`Shrine::
|
183
|
-
|
184
|
-
means that an instance of `Shrine::Attachment` is a module:
|
230
|
+
A `Shrine::Attachment` module provides a convenience model interface around the
|
231
|
+
`Shrine::Attacher` object. The `Shrine::Attachment` class is a subclass of
|
232
|
+
`Module`, which means that an instance of `Shrine::Attachment` is a module:
|
185
233
|
|
186
234
|
```rb
|
187
235
|
Shrine::Attachment.new(:image).is_a?(Module) #=> true
|
188
|
-
Shrine::Attachment.new(:image).instance_methods #=> [:image=, :image, :image_url, :image_attacher]
|
236
|
+
Shrine::Attachment.new(:image).instance_methods #=> [:image=, :image, :image_url, :image_attacher, ...]
|
189
237
|
|
190
238
|
# equivalents
|
191
239
|
Shrine::Attachment.new(:image)
|
@@ -193,30 +241,31 @@ Shrine::Attachment[:image]
|
|
193
241
|
Shrine::Attachment(:image)
|
194
242
|
```
|
195
243
|
|
196
|
-
We can include this module
|
244
|
+
We can include this module into a model:
|
197
245
|
|
198
246
|
```rb
|
199
|
-
|
200
|
-
include Shrine::Attachment(:image)
|
201
|
-
end
|
247
|
+
Photo.include Shrine::Attachment(:image)
|
202
248
|
```
|
203
249
|
```rb
|
204
|
-
photo.image = file
|
205
|
-
photo.image
|
206
|
-
photo.image_url
|
250
|
+
photo.image = file # shorthand for `photo.image_attacher.assign(file)`
|
251
|
+
photo.image # shorthand for `photo.image_attacher.get`
|
252
|
+
photo.image_url # shorthand for `photo.image_attacher.url`
|
207
253
|
|
208
|
-
photo.image_attacher #=> #<Shrine::Attacher
|
254
|
+
photo.image_attacher #=> #<Shrine::Attacher @cache_key=:cache @store_key=:store ...>
|
209
255
|
```
|
210
256
|
|
211
|
-
When a persistence plugin is loaded
|
212
|
-
automatically:
|
257
|
+
When a persistence plugin is loaded ([`activerecord`][activerecord],
|
258
|
+
[`sequel`][sequel]), the `Shrine::Attachment` module also automatically:
|
213
259
|
|
214
260
|
* syncs Shrine's validation errors with the record
|
215
261
|
* triggers promoting after record is saved
|
216
|
-
* deletes the uploaded file if attachment was replaced
|
217
|
-
destroyed
|
262
|
+
* deletes the uploaded file if attachment was replaced or the record destroyed
|
218
263
|
|
219
264
|
[Using Attacher]: https://shrinerb.com/docs/attacher
|
220
265
|
[Notes on study of shrine implementation]: https://bibwild.wordpress.com/2018/09/12/notes-on-study-of-shrine-implementation/
|
221
266
|
[Creating a New Plugin]: https://shrinerb.com/docs/creating-plugins
|
222
267
|
[Plugin system of Sequel and Roda]: https://twin.github.io/the-plugin-system-of-sequel-and-roda/
|
268
|
+
[entity]: https://shrinerb.com/docs/plugins/entity
|
269
|
+
[model]: https://shrinerb.com/docs/plugins/model
|
270
|
+
[activerecord]: https://shrinerb.com/docs/plugins/activerecord
|
271
|
+
[sequel]: https://shrinerb.com/docs/plugins/sequel
|
data/doc/external/articles.md
CHANGED
@@ -4,47 +4,62 @@ title: Articles
|
|
4
4
|
|
5
5
|
## Official articles
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
| Article | Published |
|
8
|
+
| :------- | --------: |
|
9
|
+
| [Better File Uploads with Shrine: Eager Processing](https://twin.github.io/better-file-uploads-with-shrine-eager-processing) | 12 Dec 2019 |
|
10
|
+
| [Shrine 3.0 Released](https://twin.github.io/shrine-3-0-released/) | 14 Oct 2019 |
|
11
|
+
| [Upcoming Features in Shrine 3.0](https://twin.github.io/upcoming-features-in-shrine-3-0/) | 29 Aug 2019 |
|
12
|
+
| [Better File Uploads with Shrine: Direct Uploads](https://twin.github.io/better-file-uploads-with-shrine-direct-uploads/) | 08 Jan 2018 |
|
13
|
+
| [Better File Uploads with Shrine: Metadata](https://twin.github.io/better-file-uploads-with-shrine-metadata/) | 07 Nov 2016 |
|
14
|
+
| [Better File Uploads with Shrine: Processing](https://twin.github.io/better-file-uploads-with-shrine-processing/) | 31 Oct 2016 |
|
15
|
+
| [Better File Uploads with Shrine: Attachment](https://twin.github.io/better-file-uploads-with-shrine-attachment/) | 17 Sep 2016 |
|
16
|
+
| [Better File Uploads with Shrine: Uploader](https://twin.github.io/better-file-uploads-with-shrine-uploader/) | 16 Sep 2016 |
|
17
|
+
| [Better File Uploads with Shrine: Motivation](https://twin.github.io/better-file-uploads-with-shrine-motivation/) | 11 Sep 2016 |
|
18
|
+
| [Resumable File Uploads in Ruby](https://twin.github.io/resumable-file-uploads-in-ruby/) | 04 Sep 2016 |
|
19
|
+
| [Shrine meets Transloadit](https://twin.github.io/shrine-meets-transloadit/) | 11 Jul 2016 |
|
20
|
+
| [Shrine 2.0 Released](https://twin.github.io/shrine-2-0-released/) | 20 May 2016 |
|
21
|
+
| [Asynchronous File Uploads](http://twin.github.io/file-uploads-asynchronous-world) | 18 Jan 2016 |
|
22
|
+
| [Introducing Shrine](http://twin.github.io/introducing-shrine) | 04 Oct 2015 |
|
20
23
|
|
21
24
|
## Other Articles
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
26
|
+
| Article | Published |
|
27
|
+
| :------ | --------: |
|
28
|
+
| [Microsoft Azure data storage library](https://syndicode.com/2019/12/17/microsoft-azure-data-storage-library-rewrite-the-existing-library-to-get-things-done/) | 17 Dec 2019 |
|
29
|
+
| [How to use REST clients / native apps to make Shrine client uploads and S3 work for you (no Javascript, just backend)](https://dev.to/rob117/how-to-use-rest-clients--native-apps-to-make-shrine-client-uploads-and-s3-work-for-you-no-javascript-just-backend-322h) | 16 Feb 2019 |
|
30
|
+
| [GraphQL file upload with Shrine](https://blog.stanko.io/graphql-file-upload-with-shrine-45fa26463c68) | 02 Jan 2019 |
|
31
|
+
| [Notes on study of shrine implementation](https://bibwild.wordpress.com/2018/09/12/notes-on-study-of-shrine-implementation/) | 12 Sep 2018 |
|
32
|
+
| [Happy users uploading files with Rails 5, Shrine, and Vue.js](https://itnext.io/happy-users-uploading-files-with-rails-5-shrine-and-vue-js-bbcc470a327f) | 04 Sep 2018 |
|
33
|
+
| [Rails 5 + Shrine + DropzoneJS](https://stephencodes.com/rails-5-shrine-dropzonejs/) | 20 Oct 2018 |
|
34
|
+
| [How to use Trix and Shrine for WYSIWYG Editing with Drag-and-Drop Image Uploading](http://headway.io/blog/how-to-use-trix-and-shrine-for-wysiwyg-editing-with-drag-and-drop-image-uploading/) | 26 Jan 2018 |
|
35
|
+
| [Store Your Files on S3: Uploading from a URL](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-3.html) | 28 Dec 2017 |
|
36
|
+
| [Store Your Files on S3: Direct Uploads](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-2.html) | 15 Dec 2017 |
|
37
|
+
| [Store Your Files on S3: Setup & Configuration](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-1.html) | 27 Nov 2017 |
|
38
|
+
| [Creating Streaming Radio With Rails and Icecast](https://scotch.io/tutorials/creating-online-streaming-radio-with-rails-and-icecast) | 06 Nov 2017 |
|
39
|
+
| [Multiple Photo Upload using Shrine](https://github.com/pyksoft/multi-photo-upload#multiple-photo-upload-using-shrine) | 02 Nov 2017 |
|
40
|
+
| [Uploading Files with Rails and ActionCable](https://scotch.io/tutorials/uploading-files-with-rails-and-actioncable) | 19 Oct 2017 |
|
41
|
+
| [Background file uploads to S3 using Shrine](https://elixirator.com/blog/background-file-uploads-to-s3-using-shrine/) | 21 Jul 2017 |
|
42
|
+
| [Upload images using Shrine.rb and Dropzone.js](https://codyeatworld.com/2017/04/18/rails-uploading-images-confidently-with-shrine-rb/) | 18 Apr 2017 |
|
43
|
+
| [Uploading Files With Rails and Shrine](https://code.tutsplus.com/tutorials/uploading-files-with-rails-and-shrine--cms-27596) | 26 Dec 2016 |
|
44
|
+
| [Rails File Uploading You Can Believe in with Shrine](http://www.sitepoint.com/rails-file-uploading-you-can-believe-in-with-shrine/) | 11 Apr 2016 |
|
45
|
+
| [Uploading files with Shrine in Hanami](http://katafrakt.me/2016/02/04/shrine-hanami-uploads/) | 04 Feb 2016 |
|
46
|
+
|
47
|
+
## Screencasts
|
48
|
+
|
49
|
+
| Screencast | Source | Published |
|
50
|
+
| :---- | :------ | --------: |
|
51
|
+
| [Uploading Files to DigitalOcean Spaces](https://gorails.com/episodes/digital-ocean-spaces-with-rails?autoplay=1) | GoRails | 31 Oct 2017 |
|
52
|
+
| [Trix WYSIWYG Editor And File Uploads](https://gorails.com/episodes/trix-editor?autoplay=1) | GoRails | 03 Oct 2017 |
|
53
|
+
| [Multiple File Uploads with Shrine](https://gorails.com/episodes/multiple-file-uploads-with-shrine?autoplay=1) | GoRails | 14 Dec 2016 |
|
54
|
+
| [Backgrounding and Video Transcoding](https://gorails.com/episodes/shrine-background-and-video-transcoding?autoplay=1) | GoRails | 03 Nov 2016 |
|
55
|
+
| [Direct File Uploads to S3: Part 3](https://gorails.com/episodes/direct-file-uploads-to-s3-part-3?autoplay=1) | GoRails | 05 Oct 2016 |
|
56
|
+
| [Direct File Uploads to S3: Part 2](https://gorails.com/episodes/direct-file-uploads-to-s3-part-2?autoplay=1) | GoRails | 05 Oct 2016 |
|
57
|
+
| [Direct File Uploads to S3: Part 1](https://gorails.com/episodes/direct-file-uploads-to-s3-part-1?autoplay=1) | GoRails | 05 Oct 2016 |
|
58
|
+
| [File Uploads in Rails with Shrine](https://gorails.com/episodes/file-uploading-with-shrine?autoplay=1) | GoRails | 23 Sep 2016 |
|
59
|
+
|
60
|
+
## Talks
|
61
|
+
|
62
|
+
| Talk | Source | Date |
|
63
|
+
| :---- | :------ | --------: |
|
64
|
+
| [Handling file uploads for a modern developer](https://www.youtube.com/watch?v=fP2JGjTZU2s) | wroc_love.rb | 24 Mar 2019 |
|
65
|
+
| [Shrine – Handle File Uploads like it's 2017](https://www.youtube.com/watch?v=plD-RkKEay0) | Melbourne Ruby | 27 Feb 2017 |
|