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/refile.md
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Upgrading from Refile
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
This guide is aimed at helping Refile users transition to Shrine, and it consists
|
|
4
6
|
of three parts:
|
|
5
7
|
|
|
6
8
|
1. Explanation of the key differences in design between Refile and Shrine
|
|
7
|
-
2. Instructions how to migrate
|
|
9
|
+
2. Instructions how to migrate an existing app that uses Refile to Shrine
|
|
8
10
|
3. Extensive reference of Refile's interface with Shrine equivalents
|
|
9
11
|
|
|
10
|
-
##
|
|
12
|
+
## Overview
|
|
11
13
|
|
|
12
14
|
Shrine borrows many great concepts from Refile: Refile's "backends" are here
|
|
13
|
-
named "storages", it uses the same IO abstraction for uploading and
|
|
14
|
-
uploaded files, similar attachment logic, and direct uploads are
|
|
15
|
+
named "storages", it uses the same IO abstraction for uploading and
|
|
16
|
+
representing uploaded files, similar attachment logic, and direct uploads are
|
|
17
|
+
supported as well.
|
|
18
|
+
|
|
19
|
+
### Uploader
|
|
15
20
|
|
|
16
21
|
While in Refile you work with storages directly, Shrine uses *uploaders* which
|
|
17
22
|
wrap storage uploads:
|
|
@@ -25,66 +30,27 @@ uploaded_file #=> #<Shrine::UploadedFile ...>
|
|
|
25
30
|
uploaded_file.storage #=> #<Shrine::Storage::S3>
|
|
26
31
|
```
|
|
27
32
|
|
|
28
|
-
This way Shrine can perform tasks like generating location, extracting
|
|
33
|
+
This way, Shrine can perform tasks like generating location, extracting
|
|
29
34
|
metadata, processing, and logging, which are all storage-agnostic, and leave
|
|
30
35
|
storages to deal only with actual file storage. And these tasks can be
|
|
31
36
|
configured differently depending on the types of files you're uploading:
|
|
32
37
|
|
|
33
38
|
```rb
|
|
34
39
|
class ImageUploader < Shrine
|
|
35
|
-
add_metadata :exif do |io
|
|
40
|
+
add_metadata :exif do |io|
|
|
36
41
|
MiniMagick::Image.new(io).exif
|
|
37
42
|
end
|
|
38
43
|
end
|
|
39
44
|
```
|
|
40
45
|
```rb
|
|
41
46
|
class VideoUploader < Shrine
|
|
42
|
-
add_metadata :duration do |io
|
|
47
|
+
add_metadata :duration do |io|
|
|
43
48
|
FFMPEG::Movie.new(io.path).duration
|
|
44
49
|
end
|
|
45
50
|
end
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Refile implements on-the-fly processing, serving all files through the Rack
|
|
51
|
-
endpoint. However, it doesn't offer any abilities for processing on upload.
|
|
52
|
-
Shrine, on the other hand, generates URLs to specific storages and offers
|
|
53
|
-
processing on upload (like CarrierWave and Paperclip), but doesn't support
|
|
54
|
-
on-the-fly processing.
|
|
55
|
-
|
|
56
|
-
The reason for this decision is that an image server is a completely separate
|
|
57
|
-
responsibility, and it's better to use any of the generic services for
|
|
58
|
-
on-the-fly processing. Shrine already has integrations for many such services:
|
|
59
|
-
[shrine-cloudinary], [shrine-imgix], and [shrine-uploadcare]. There is even
|
|
60
|
-
an open-source solution, [Attache], which you can also use with Shrine.
|
|
61
|
-
|
|
62
|
-
This is how you would process multiple versions in Shrine:
|
|
63
|
-
|
|
64
|
-
```rb
|
|
65
|
-
require "image_processing/mini_magick"
|
|
66
|
-
|
|
67
|
-
class ImageUploader < Shrine
|
|
68
|
-
plugin :processing
|
|
69
|
-
plugin :versions
|
|
70
|
-
|
|
71
|
-
process(:store) do |io, context|
|
|
72
|
-
versions = { original: io } # retain original
|
|
73
|
-
|
|
74
|
-
io.download do |original|
|
|
75
|
-
pipeline = ImageProcessing::MiniMagick.source(original)
|
|
76
|
-
|
|
77
|
-
versions[:large] = pipeline.resize_to_limit!(800, 800)
|
|
78
|
-
versions[:medium] = pipeline.resize_to_limit!(500, 500)
|
|
79
|
-
versions[:small] = pipeline.resize_to_limit!(300, 300)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
versions # return the hash of processed files
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### URL
|
|
53
|
+
#### URL
|
|
88
54
|
|
|
89
55
|
While Refile serves all files through the Rack endpoint mounted in your app,
|
|
90
56
|
Shrine serves files directly from storage services:
|
|
@@ -99,103 +65,113 @@ Refile.attachment_url(@photo, :image) #=> "/attachments/cache/50dfl833lfs0gfh.jp
|
|
|
99
65
|
|
|
100
66
|
If you're using storage which don't expose files over URL (e.g. a database
|
|
101
67
|
storage), or you want to secure your downloads, you can also serve files
|
|
102
|
-
through your app using the download_endpoint plugin.
|
|
68
|
+
through your app using the [`download_endpoint`][download_endpoint] plugin.
|
|
103
69
|
|
|
104
|
-
|
|
70
|
+
### Persistence
|
|
105
71
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
72
|
+
Refile persists the uploaded file location and metadata into individual
|
|
73
|
+
columns:
|
|
74
|
+
|
|
75
|
+
* `<attachment>_id`
|
|
76
|
+
* `<attachment>_filename`
|
|
77
|
+
* `<attachment>_content_type`
|
|
78
|
+
* `<attachment>_size`
|
|
79
|
+
|
|
80
|
+
Shrine, on the other hand, saves all uploaded file data into a single
|
|
81
|
+
`<attachment>_data` column:
|
|
110
82
|
|
|
111
83
|
```rb
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
84
|
+
{
|
|
85
|
+
"id": "path/to/image.jpg",
|
|
86
|
+
"storage": "store",
|
|
87
|
+
"metadata": {
|
|
88
|
+
"filename": "nature.jpg",
|
|
89
|
+
"size": 4739472,
|
|
90
|
+
"mime_type": "image/jpeg"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
116
93
|
```
|
|
117
|
-
|
|
118
94
|
```rb
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
end
|
|
95
|
+
photo.image.id #=> "path/to/image.jpg"
|
|
96
|
+
photo.image.storage_key #=> :store
|
|
97
|
+
photo.image.metadata #=> { "filename" => "...", "size" => ..., "mime_type" => "..." }
|
|
123
98
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
99
|
+
photo.image.original_filename #=> "nature.jpg"
|
|
100
|
+
photo.image.size #=> 4739472
|
|
101
|
+
photo.image.mime_type #=> "image/jpeg"
|
|
127
102
|
```
|
|
128
103
|
|
|
129
|
-
This
|
|
130
|
-
|
|
104
|
+
This column can be queried if it's made a JSON column. Alternatively, you can
|
|
105
|
+
use the [`metadata_attributes`][metadata_attributes] plugin to save metadata
|
|
106
|
+
into separate columns.
|
|
131
107
|
|
|
132
|
-
###
|
|
133
|
-
|
|
134
|
-
Refile allows you to save additional metadata about uploaded files in additional
|
|
135
|
-
columns, so you can define `<attachment>_filename`, `<attachment>_content_type`,
|
|
136
|
-
or `<attachment>_size`.
|
|
108
|
+
### Processing
|
|
137
109
|
|
|
138
|
-
Shrine
|
|
139
|
-
|
|
110
|
+
Shrine provides on-the-fly processing via the
|
|
111
|
+
[`derivation_endpoint`][derivation_endpoint] plugin:
|
|
140
112
|
|
|
141
113
|
```rb
|
|
142
|
-
|
|
143
|
-
# {
|
|
144
|
-
# "storage" => "store",
|
|
145
|
-
# "id" => "photo/1/image/0d9o8dk42.png",
|
|
146
|
-
# "metadata" => {
|
|
147
|
-
# "filename" => "nature.png",
|
|
148
|
-
# "size" => 49349138,
|
|
149
|
-
# "mime_type" => "image/png"
|
|
150
|
-
# }
|
|
151
|
-
# }
|
|
114
|
+
require "image_processing/mini_magick"
|
|
152
115
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
116
|
+
class ImageUploader < Shrine
|
|
117
|
+
plugin :derivation_endpoint,
|
|
118
|
+
secret_key: "<YOUR SECRET KEY>",
|
|
119
|
+
prefix: "derivations/image" # needs to match the mount point in routes
|
|
120
|
+
|
|
121
|
+
derivation :thumbnail do |file, width, height|
|
|
122
|
+
ImageProcessing::MiniMagick
|
|
123
|
+
.source(file)
|
|
124
|
+
.resize_to_limit!(width.to_i, height.to_i)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
```
|
|
128
|
+
```rb
|
|
129
|
+
# config/routes.rb (Rails)
|
|
130
|
+
Rails.application.routes.draw do
|
|
131
|
+
# ...
|
|
132
|
+
mount ImageUploader.derivation_endpoint => "/derivations/image"
|
|
133
|
+
end
|
|
156
134
|
```
|
|
157
135
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
to add their own metadata.
|
|
136
|
+
Shrine also support eager processing using the [`derivatives`][derivatives]
|
|
137
|
+
plugin.
|
|
161
138
|
|
|
162
|
-
###
|
|
139
|
+
### Validation
|
|
163
140
|
|
|
164
|
-
In Refile
|
|
165
|
-
in Shrine you define validations on the instance-level, which allows them to
|
|
166
|
-
be dynamic:
|
|
141
|
+
In Refile, file validation is defined statically on attachment definition:
|
|
167
142
|
|
|
168
143
|
```rb
|
|
169
144
|
class Photo < Sequel::Model
|
|
170
145
|
attachment :image,
|
|
171
|
-
extension: %w[jpg jpeg png
|
|
172
|
-
content_type: %w[image/jpeg image/png image/
|
|
146
|
+
extension: %w[jpg jpeg png webp],
|
|
147
|
+
content_type: %w[image/jpeg image/png image/webp]
|
|
173
148
|
end
|
|
174
149
|
```
|
|
175
150
|
|
|
151
|
+
In Shrine, validation is performed on the instance-level, which allows you to
|
|
152
|
+
make the validation conditional:
|
|
153
|
+
|
|
176
154
|
```rb
|
|
177
155
|
class ImageUploader < Shrine
|
|
178
156
|
plugin :validation_helpers
|
|
179
157
|
|
|
180
158
|
Attacher.validate do
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
159
|
+
validate_max_size 10*1024*1024
|
|
160
|
+
validate_extension %w[jpg jpeg png webp]
|
|
161
|
+
|
|
162
|
+
if validate_mime_type %w[image/jpeg image/png image/webp]
|
|
163
|
+
validate_max_dimensions [5000, 5000]
|
|
164
|
+
end
|
|
184
165
|
end
|
|
185
166
|
end
|
|
186
167
|
```
|
|
187
168
|
|
|
188
169
|
Refile extracts the MIME type from the file extension, which means it can
|
|
189
170
|
easily be spoofed (just give a PHP file a `.jpg` extension). Shrine has the
|
|
190
|
-
determine_mime_type plugin for determining MIME type
|
|
191
|
-
|
|
192
|
-
### Multiple uploads
|
|
193
|
-
|
|
194
|
-
Shrine doesn't have a built-in solution for accepting multiple uploads, but
|
|
195
|
-
it's actually very easy to do manually, see the [demo app] on how you can do
|
|
196
|
-
multiple uploads directly to S3.
|
|
171
|
+
[`determine_mime_type`][determine_mime_type] plugin for determining MIME type
|
|
172
|
+
from file *content*.
|
|
197
173
|
|
|
198
|
-
|
|
174
|
+
### Direct uploads
|
|
199
175
|
|
|
200
176
|
Shrine borrows Refile's idea of direct uploads, and ships with
|
|
201
177
|
`upload_endpoint` and `presign_endpoint` plugins which provide endpoints for
|
|
@@ -209,44 +185,68 @@ Shrine.plugin :upload_endpoint
|
|
|
209
185
|
Shrine.presign_endpoint(:cache) # Rack app that generates presigns for specified storage
|
|
210
186
|
```
|
|
211
187
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
188
|
+
While Refile ships with a plug-and-play JavaScript for direct uploads, Shrine
|
|
189
|
+
instead adopts [Uppy], a modern and modular JavaScript file upload library that
|
|
190
|
+
happens to integrate well with Shrine.
|
|
191
|
+
|
|
192
|
+
### Multiple uploads
|
|
193
|
+
|
|
194
|
+
Shrine doesn't have support for multiple uploads out-of-the-box like Refile
|
|
195
|
+
does. Instead, you can implement them using a separate table with a one-to-many
|
|
196
|
+
relationship to which the files will be attached. The [Multiple Files] guide
|
|
197
|
+
explains this setup in more detail.
|
|
216
198
|
|
|
217
199
|
## Migrating from Refile
|
|
218
200
|
|
|
219
201
|
You have an existing app using Refile and you want to transfer it to
|
|
220
|
-
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
|
221
|
-
|
|
202
|
+
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
|
203
|
+
|
|
204
|
+
### 1. Add Shrine column
|
|
205
|
+
|
|
206
|
+
First we need to create the `image_data` column for Shrine:
|
|
222
207
|
|
|
223
208
|
```rb
|
|
224
209
|
add_column :photos, :image_data, :text
|
|
225
210
|
```
|
|
226
211
|
|
|
212
|
+
### 2. Dual write
|
|
213
|
+
|
|
227
214
|
Afterwards we need to make new uploads write to the `image_data` column. This
|
|
228
215
|
can be done by including the below module to all models that have Refile
|
|
229
216
|
attachments:
|
|
230
217
|
|
|
231
218
|
```rb
|
|
219
|
+
require "shrine"
|
|
220
|
+
|
|
221
|
+
Shrine.storages = {
|
|
222
|
+
cache: ...,
|
|
223
|
+
store: ...,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
Shrine.plugin :model
|
|
227
|
+
|
|
232
228
|
module RefileShrineSynchronization
|
|
233
229
|
def write_shrine_data(name)
|
|
234
|
-
|
|
235
|
-
data = {
|
|
236
|
-
storage: :store,
|
|
237
|
-
id: send("#{name}_id"),
|
|
238
|
-
metadata: {
|
|
239
|
-
size: (send("#{name}_size") if respond_to?("#{name}_size")),
|
|
240
|
-
filename: (send("#{name}_filename") if respond_to?("#{name}_filename")),
|
|
241
|
-
mime_type: (send("#{name}_content_type") if respond_to?("#{name}_content_type")),
|
|
242
|
-
}
|
|
243
|
-
}
|
|
230
|
+
attacher = Shrine::Attacher.from_model(self, name)
|
|
244
231
|
|
|
245
|
-
|
|
232
|
+
if read_attribute("#{name}_id").present?
|
|
233
|
+
attacher.set shrine_file(name)
|
|
246
234
|
else
|
|
247
|
-
|
|
235
|
+
attacher.set nil
|
|
248
236
|
end
|
|
249
237
|
end
|
|
238
|
+
|
|
239
|
+
def shrine_file(name)
|
|
240
|
+
Shrine.uploaded_file(
|
|
241
|
+
storage: :store,
|
|
242
|
+
id: send("#{name}_id"),
|
|
243
|
+
metadata: {
|
|
244
|
+
"size" => (send("#{name}_size") if respond_to?("#{name}_size")),
|
|
245
|
+
"filename" => (send("#{name}_filename") if respond_to?("#{name}_filename")),
|
|
246
|
+
"mime_type" => (send("#{name}_content_type") if respond_to?("#{name}_content_type")),
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
end
|
|
250
250
|
end
|
|
251
251
|
```
|
|
252
252
|
```rb
|
|
@@ -255,14 +255,18 @@ class Photo < ActiveRecord::Base
|
|
|
255
255
|
include RefileShrineSynchronization
|
|
256
256
|
|
|
257
257
|
before_save do
|
|
258
|
-
write_shrine_data(:image) if
|
|
258
|
+
write_shrine_data(:image) if image_id_changed?
|
|
259
259
|
end
|
|
260
260
|
end
|
|
261
261
|
```
|
|
262
262
|
|
|
263
263
|
After you deploy this code, the `image_data` column should now be successfully
|
|
264
|
-
synchronized with new attachments.
|
|
265
|
-
|
|
264
|
+
synchronized with new attachments.
|
|
265
|
+
|
|
266
|
+
### 3. Data migration
|
|
267
|
+
|
|
268
|
+
Next step is to run a script which writes all existing Refile attachments to
|
|
269
|
+
`image_data`:
|
|
266
270
|
|
|
267
271
|
```rb
|
|
268
272
|
Photo.find_each do |photo|
|
|
@@ -271,9 +275,22 @@ Photo.find_each do |photo|
|
|
|
271
275
|
end
|
|
272
276
|
```
|
|
273
277
|
|
|
278
|
+
### 4. Rewrite code
|
|
279
|
+
|
|
274
280
|
Now you should be able to rewrite your application so that it uses Shrine
|
|
275
|
-
instead of Refile
|
|
276
|
-
the
|
|
281
|
+
instead of Refile (you can consult the reference in the next section). You can
|
|
282
|
+
remove the `RefileShrineSynchronization` module as well.
|
|
283
|
+
|
|
284
|
+
### 5. Remove Refile columns
|
|
285
|
+
|
|
286
|
+
If everything is looking good, we can remove Refile columns:
|
|
287
|
+
|
|
288
|
+
```rb
|
|
289
|
+
remove_column :photos, :image_id
|
|
290
|
+
remove_column :photos, :image_size
|
|
291
|
+
remove_column :photos, :image_filename
|
|
292
|
+
remove_column :photos, :image_content_type
|
|
293
|
+
```
|
|
277
294
|
|
|
278
295
|
## Refile to Shrine direct mapping
|
|
279
296
|
|
|
@@ -293,8 +310,8 @@ Shrine.storages = {
|
|
|
293
310
|
|
|
294
311
|
#### `.app`, `.mount_point`, `.automount`
|
|
295
312
|
|
|
296
|
-
The
|
|
297
|
-
|
|
313
|
+
The Rack apps provided by the `*_endpoint` Shrine plugins are mounted
|
|
314
|
+
explicitly:
|
|
298
315
|
|
|
299
316
|
```rb
|
|
300
317
|
# config/routes.rb
|
|
@@ -306,8 +323,8 @@ end
|
|
|
306
323
|
|
|
307
324
|
#### `.allow_uploads_to`
|
|
308
325
|
|
|
309
|
-
The `Shrine.upload_endpoint` and `Shrine.presign_endpoint` require you
|
|
310
|
-
specify the storage that will be used.
|
|
326
|
+
The `Shrine.upload_endpoint` and `Shrine.presign_endpoint` builders require you
|
|
327
|
+
to specify the storage that will be used.
|
|
311
328
|
|
|
312
329
|
#### `.logger`
|
|
313
330
|
|
|
@@ -318,10 +335,10 @@ Shrine.logger
|
|
|
318
335
|
#### `.processors`, `.processor`
|
|
319
336
|
|
|
320
337
|
```rb
|
|
321
|
-
class
|
|
322
|
-
plugin :
|
|
338
|
+
class ImageUploader < Shrine
|
|
339
|
+
plugin :derivatives
|
|
323
340
|
|
|
324
|
-
|
|
341
|
+
derivation :thumbnail do |file, width, height|
|
|
325
342
|
# ...
|
|
326
343
|
end
|
|
327
344
|
end
|
|
@@ -329,7 +346,7 @@ end
|
|
|
329
346
|
|
|
330
347
|
#### `.types`
|
|
331
348
|
|
|
332
|
-
|
|
349
|
+
Shrine defines validations on the uploader class level:
|
|
333
350
|
|
|
334
351
|
```rb
|
|
335
352
|
class MyUploader < Shrine
|
|
@@ -341,42 +358,45 @@ class MyUploader < Shrine
|
|
|
341
358
|
end
|
|
342
359
|
```
|
|
343
360
|
|
|
344
|
-
#### `.extract_filename
|
|
361
|
+
#### `.extract_filename`
|
|
345
362
|
|
|
346
|
-
|
|
347
|
-
`Shrine#
|
|
363
|
+
Shrine's equivalent is a `Shrine#extract_filename` private method. You can
|
|
364
|
+
instead use the `Shrine#extract_metadata` public method.
|
|
348
365
|
|
|
349
|
-
#### `.
|
|
366
|
+
#### `.extract_content_type`
|
|
350
367
|
|
|
351
|
-
|
|
352
|
-
|
|
368
|
+
The [`determine_mime_type`][determine_mime_type] plugin provides a
|
|
369
|
+
`Shrine.determine_mime_type` method.
|
|
353
370
|
|
|
354
|
-
#### `.
|
|
371
|
+
#### `.app_url`, `.upload_url`, `.attachment_upload_url`, `.presign_url`, `.attachment_presign_url`
|
|
355
372
|
|
|
356
|
-
|
|
357
|
-
|
|
373
|
+
Shrine requires you to use your framework to generate URLs to mounted
|
|
374
|
+
endpoints.
|
|
358
375
|
|
|
359
|
-
#### `.
|
|
376
|
+
#### `.attachment_url`, `.file_url`
|
|
360
377
|
|
|
361
|
-
|
|
362
|
-
the
|
|
378
|
+
You can call `#url` on the uploaded file, or `#<name>_url` on the model.
|
|
379
|
+
Alternatively, you can use `#download_url` provided by the `download_endpoint`
|
|
380
|
+
plugin.
|
|
363
381
|
|
|
364
382
|
#### `.host`, `.cdn_host`, `.app_host`, `.allow_downloads_from`, `allow_origin`, `.content_max_age`
|
|
365
383
|
|
|
366
|
-
|
|
384
|
+
These can be configured on individual `*_endpoint` plugins.
|
|
367
385
|
|
|
368
386
|
#### `.secret_key`, `.token`, `.valid_token?`
|
|
369
387
|
|
|
370
|
-
|
|
388
|
+
The secret key is required for the
|
|
389
|
+
[`derivation_endpoint`][derivation_endpoint], but these methods are not
|
|
390
|
+
exposed.
|
|
371
391
|
|
|
372
|
-
### `
|
|
392
|
+
### `Attachment`
|
|
373
393
|
|
|
374
394
|
Shrine's equivalent to calling the attachment is including an attachment module
|
|
375
395
|
of an uploader:
|
|
376
396
|
|
|
377
397
|
```rb
|
|
378
|
-
class
|
|
379
|
-
include ImageUploader::Attachment
|
|
398
|
+
class Photo
|
|
399
|
+
include ImageUploader::Attachment(:image)
|
|
380
400
|
end
|
|
381
401
|
```
|
|
382
402
|
|
|
@@ -390,8 +410,8 @@ class ImageUploader < Shrine
|
|
|
390
410
|
plugin :validation_helpers
|
|
391
411
|
|
|
392
412
|
Attacher.validate do
|
|
393
|
-
|
|
394
|
-
|
|
413
|
+
validate_extension %w[jpg jpeg png]
|
|
414
|
+
validate_mime_type %w[image/jpeg image/png]
|
|
395
415
|
end
|
|
396
416
|
end
|
|
397
417
|
```
|
|
@@ -417,7 +437,7 @@ No equivalent currently exists in Shrine.
|
|
|
417
437
|
|
|
418
438
|
### `accepts_attachments_for`
|
|
419
439
|
|
|
420
|
-
No equivalent in Shrine, but take a look at the
|
|
440
|
+
No equivalent in Shrine, but take a look at the [Multiple Files] guide.
|
|
421
441
|
|
|
422
442
|
### Form helpers
|
|
423
443
|
|
|
@@ -438,7 +458,7 @@ Shrine.plugin :cached_attachment_data
|
|
|
438
458
|
```
|
|
439
459
|
```rb
|
|
440
460
|
form_for @user do |form|
|
|
441
|
-
form.hidden_field :profile_image, value: @user.cached_profile_image_data
|
|
461
|
+
form.hidden_field :profile_image, value: @user.cached_profile_image_data, id: nil
|
|
442
462
|
form.file_field :profile_image
|
|
443
463
|
end
|
|
444
464
|
```
|
|
@@ -455,7 +475,7 @@ Shrine.plugin :remove_attachment
|
|
|
455
475
|
```
|
|
456
476
|
```rb
|
|
457
477
|
form_for @user do |form|
|
|
458
|
-
form.hidden_field :profile_image, value: @user.cached_profile_image_data
|
|
478
|
+
form.hidden_field :profile_image, value: @user.cached_profile_image_data, id: nil
|
|
459
479
|
form.file_field :profile_image
|
|
460
480
|
form.check_box :remove_profile_image
|
|
461
481
|
end
|
|
@@ -471,18 +491,16 @@ Shrine.plugin :remote_url
|
|
|
471
491
|
```
|
|
472
492
|
```rb
|
|
473
493
|
form_for @user do |form|
|
|
474
|
-
form.hidden_field :profile_image, value: @user.cached_profile_image_data
|
|
494
|
+
form.hidden_field :profile_image, value: @user.cached_profile_image_data, id: nil
|
|
475
495
|
form.file_field :profile_image
|
|
476
496
|
form.text_field :profile_image_remote_url
|
|
477
497
|
end
|
|
478
498
|
```
|
|
479
499
|
|
|
480
|
-
[shrine-cloudinary]: https://github.com/shrinerb/shrine-cloudinary
|
|
481
|
-
[shrine-imgix]: https://github.com/shrinerb/shrine-imgix
|
|
482
|
-
[shrine-uploadcare]: https://github.com/shrinerb/shrine-uploadcare
|
|
483
|
-
[Attache]: https://github.com/choonkeat/attache
|
|
484
|
-
[image_processing]: https://github.com/janko/image_processing
|
|
485
500
|
[Uppy]: https://uppy.io
|
|
486
|
-
[
|
|
487
|
-
[
|
|
488
|
-
[
|
|
501
|
+
[derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
|
|
502
|
+
[download_endpoint]: https://shrinerb.com/docs/plugins/download_endpoint
|
|
503
|
+
[derivatives]: https://shrinerb.com/docs/plugins/derivatives
|
|
504
|
+
[metadata_attributes]: https://shrinerb.com/docs/plugins/metadata_attributes
|
|
505
|
+
[determine_mime_type]: https://shrinerb.com/docs/plugins/determine_mime_type
|
|
506
|
+
[Multiple Files]: https://shrinerb.com/docs/multiple-files
|
data/doc/release_notes/1.0.0.md
CHANGED
data/doc/release_notes/1.1.0.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 1.1.0
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# New plugins
|
|
2
6
|
|
|
3
7
|
* The `download_endpoint` plugin has been added, which allows downloading files
|
|
@@ -39,11 +43,11 @@ plugin :keep_location, :cache => :store
|
|
|
39
43
|
```rb
|
|
40
44
|
user = User.new
|
|
41
45
|
user.avatar = image
|
|
42
|
-
user.avatar.storage_key #=>
|
|
46
|
+
user.avatar.storage_key #=> :cache
|
|
43
47
|
user.avatar.id #=> "abc123.jpg"
|
|
44
48
|
|
|
45
49
|
user.save
|
|
46
|
-
user.avatar.storage_key #=>
|
|
50
|
+
user.avatar.storage_key #=> :store
|
|
47
51
|
user.avatar.id #=> "abc123.jpg"
|
|
48
52
|
```
|
|
49
53
|
|
data/doc/release_notes/1.2.0.md
CHANGED
data/doc/release_notes/1.3.0.md
CHANGED
data/doc/release_notes/1.4.0.md
CHANGED
data/doc/release_notes/1.4.1.md
CHANGED
data/doc/release_notes/1.4.2.md
CHANGED
data/doc/release_notes/2.0.0.md
CHANGED