shrine 3.0.0.rc → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of shrine might be problematic. Click here for more details.

Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -66
  3. data/README.md +39 -1061
  4. data/doc/advantages.md +151 -148
  5. data/doc/attacher.md +12 -30
  6. data/doc/carrierwave.md +150 -115
  7. data/doc/changing_derivatives.md +5 -11
  8. data/doc/changing_location.md +8 -5
  9. data/doc/changing_storage.md +5 -2
  10. data/doc/creating_persistence_plugins.md +9 -6
  11. data/doc/creating_plugins.md +42 -22
  12. data/doc/creating_storages.md +4 -1
  13. data/doc/design.md +7 -5
  14. data/doc/direct_s3.md +9 -4
  15. data/doc/external/articles.md +50 -0
  16. data/doc/external/extensions.md +46 -0
  17. data/doc/external/misc.md +17 -0
  18. data/doc/getting_started.md +1038 -0
  19. data/doc/metadata.md +5 -3
  20. data/doc/multiple_files.md +55 -29
  21. data/doc/paperclip.md +206 -163
  22. data/doc/plugins/activerecord.md +26 -6
  23. data/doc/plugins/add_metadata.md +4 -2
  24. data/doc/plugins/atomic_helpers.md +4 -2
  25. data/doc/plugins/backgrounding.md +83 -44
  26. data/doc/plugins/cached_attachment_data.md +4 -2
  27. data/doc/plugins/column.md +4 -2
  28. data/doc/plugins/data_uri.md +10 -6
  29. data/doc/plugins/default_storage.md +5 -3
  30. data/doc/plugins/default_url.md +4 -2
  31. data/doc/plugins/delete_raw.md +4 -2
  32. data/doc/plugins/derivation_endpoint.md +63 -39
  33. data/doc/plugins/derivatives.md +13 -50
  34. data/doc/plugins/determine_mime_type.md +6 -4
  35. data/doc/plugins/download_endpoint.md +6 -3
  36. data/doc/plugins/dynamic_storage.md +4 -2
  37. data/doc/plugins/entity.md +6 -4
  38. data/doc/plugins/form_assign.md +4 -2
  39. data/doc/plugins/included.md +4 -2
  40. data/doc/plugins/infer_extension.md +6 -4
  41. data/doc/plugins/instrumentation.md +5 -3
  42. data/doc/plugins/keep_files.md +9 -2
  43. data/doc/plugins/metadata_attributes.md +5 -3
  44. data/doc/plugins/mirroring.md +4 -2
  45. data/doc/plugins/model.md +6 -4
  46. data/doc/plugins/module_include.md +4 -2
  47. data/doc/plugins/multi_cache.md +4 -2
  48. data/doc/plugins/persistence.md +5 -3
  49. data/doc/plugins/presign_endpoint.md +6 -2
  50. data/doc/plugins/pretty_location.md +5 -3
  51. data/doc/plugins/processing.md +4 -2
  52. data/doc/plugins/rack_file.md +8 -2
  53. data/doc/plugins/rack_response.md +6 -2
  54. data/doc/plugins/recache.md +4 -2
  55. data/doc/plugins/refresh_metadata.md +5 -3
  56. data/doc/plugins/remote_url.md +26 -5
  57. data/doc/plugins/remove_attachment.md +4 -2
  58. data/doc/plugins/remove_invalid.md +10 -2
  59. data/doc/plugins/restore_cached_data.md +9 -3
  60. data/doc/plugins/sequel.md +26 -6
  61. data/doc/plugins/signature.md +6 -4
  62. data/doc/plugins/store_dimensions.md +6 -4
  63. data/doc/plugins/tempfile.md +4 -2
  64. data/doc/plugins/upload_endpoint.md +6 -2
  65. data/doc/plugins/upload_options.md +6 -4
  66. data/doc/plugins/url_options.md +4 -2
  67. data/doc/plugins/validation.md +7 -3
  68. data/doc/plugins/validation_helpers.md +13 -10
  69. data/doc/plugins/versions.md +4 -8
  70. data/doc/processing.md +27 -9
  71. data/doc/refile.md +119 -127
  72. data/doc/release_notes/1.0.0.md +4 -0
  73. data/doc/release_notes/1.1.0.md +4 -0
  74. data/doc/release_notes/1.2.0.md +4 -0
  75. data/doc/release_notes/1.3.0.md +4 -0
  76. data/doc/release_notes/1.4.0.md +4 -0
  77. data/doc/release_notes/1.4.1.md +4 -0
  78. data/doc/release_notes/1.4.2.md +4 -0
  79. data/doc/release_notes/2.0.0.md +4 -0
  80. data/doc/release_notes/2.0.1.md +4 -0
  81. data/doc/release_notes/2.1.0.md +4 -0
  82. data/doc/release_notes/2.1.1.md +4 -0
  83. data/doc/release_notes/2.10.0.md +4 -0
  84. data/doc/release_notes/2.10.1.md +4 -0
  85. data/doc/release_notes/2.11.0.md +4 -0
  86. data/doc/release_notes/2.12.0.md +4 -0
  87. data/doc/release_notes/2.13.0.md +4 -0
  88. data/doc/release_notes/2.14.0.md +5 -1
  89. data/doc/release_notes/2.15.0.md +10 -6
  90. data/doc/release_notes/2.16.0.md +4 -0
  91. data/doc/release_notes/2.17.0.md +4 -0
  92. data/doc/release_notes/2.18.0.md +4 -0
  93. data/doc/release_notes/2.19.0.md +7 -4
  94. data/doc/release_notes/2.2.0.md +4 -0
  95. data/doc/release_notes/2.3.0.md +4 -0
  96. data/doc/release_notes/2.3.1.md +4 -0
  97. data/doc/release_notes/2.4.0.md +4 -0
  98. data/doc/release_notes/2.4.1.md +4 -0
  99. data/doc/release_notes/2.5.0.md +4 -0
  100. data/doc/release_notes/2.6.0.md +4 -0
  101. data/doc/release_notes/2.6.1.md +4 -0
  102. data/doc/release_notes/2.7.0.md +4 -0
  103. data/doc/release_notes/2.8.0.md +4 -0
  104. data/doc/release_notes/2.9.0.md +4 -0
  105. data/doc/release_notes/3.0.0.md +120 -38
  106. data/doc/retrieving_uploads.md +4 -1
  107. data/doc/securing_uploads.md +4 -1
  108. data/doc/storage/file_system.md +12 -4
  109. data/doc/storage/s3.md +4 -2
  110. data/doc/testing.md +27 -41
  111. data/doc/upgrading_to_3.md +105 -26
  112. data/doc/validation.md +8 -6
  113. data/lib/shrine/attacher.rb +2 -2
  114. data/lib/shrine/attachment.rb +7 -10
  115. data/lib/shrine/plugins/activerecord.rb +10 -10
  116. data/lib/shrine/plugins/add_metadata.rb +1 -3
  117. data/lib/shrine/plugins/atomic_helpers.rb +6 -8
  118. data/lib/shrine/plugins/backgrounding.rb +4 -6
  119. data/lib/shrine/plugins/cached_attachment_data.rb +1 -3
  120. data/lib/shrine/plugins/column.rb +2 -4
  121. data/lib/shrine/plugins/data_uri.rb +1 -3
  122. data/lib/shrine/plugins/default_storage.rb +1 -3
  123. data/lib/shrine/plugins/default_url.rb +1 -3
  124. data/lib/shrine/plugins/delete_raw.rb +1 -3
  125. data/lib/shrine/plugins/derivation_endpoint.rb +3 -4
  126. data/lib/shrine/plugins/derivatives.rb +2 -4
  127. data/lib/shrine/plugins/determine_mime_type.rb +1 -3
  128. data/lib/shrine/plugins/download_endpoint.rb +1 -3
  129. data/lib/shrine/plugins/dynamic_storage.rb +1 -3
  130. data/lib/shrine/plugins/entity.rb +25 -9
  131. data/lib/shrine/plugins/form_assign.rb +1 -3
  132. data/lib/shrine/plugins/included.rb +1 -3
  133. data/lib/shrine/plugins/infer_extension.rb +1 -3
  134. data/lib/shrine/plugins/instrumentation.rb +1 -3
  135. data/lib/shrine/plugins/keep_files.rb +1 -3
  136. data/lib/shrine/plugins/metadata_attributes.rb +1 -3
  137. data/lib/shrine/plugins/mirroring.rb +2 -1
  138. data/lib/shrine/plugins/model.rb +2 -4
  139. data/lib/shrine/plugins/module_include.rb +1 -3
  140. data/lib/shrine/plugins/multi_cache.rb +3 -3
  141. data/lib/shrine/plugins/presign_endpoint.rb +1 -3
  142. data/lib/shrine/plugins/pretty_location.rb +1 -3
  143. data/lib/shrine/plugins/processing.rb +1 -3
  144. data/lib/shrine/plugins/rack_file.rb +1 -3
  145. data/lib/shrine/plugins/rack_response.rb +1 -3
  146. data/lib/shrine/plugins/recache.rb +1 -3
  147. data/lib/shrine/plugins/refresh_metadata.rb +1 -3
  148. data/lib/shrine/plugins/remote_url.rb +1 -3
  149. data/lib/shrine/plugins/remove_attachment.rb +1 -3
  150. data/lib/shrine/plugins/remove_invalid.rb +1 -3
  151. data/lib/shrine/plugins/restore_cached_data.rb +1 -3
  152. data/lib/shrine/plugins/sequel.rb +10 -12
  153. data/lib/shrine/plugins/signature.rb +1 -3
  154. data/lib/shrine/plugins/store_dimensions.rb +1 -3
  155. data/lib/shrine/plugins/tempfile.rb +1 -3
  156. data/lib/shrine/plugins/upload_endpoint.rb +1 -3
  157. data/lib/shrine/plugins/upload_options.rb +1 -3
  158. data/lib/shrine/plugins/url_options.rb +1 -3
  159. data/lib/shrine/plugins/validation.rb +1 -3
  160. data/lib/shrine/plugins/validation_helpers.rb +1 -3
  161. data/lib/shrine/plugins/versions.rb +1 -3
  162. data/lib/shrine/storage/file_system.rb +1 -1
  163. data/lib/shrine/storage/linter.rb +1 -1
  164. data/lib/shrine/storage/memory.rb +2 -1
  165. data/lib/shrine/storage/s3.rb +3 -3
  166. data/lib/shrine/version.rb +1 -1
  167. metadata +8 -4
@@ -1,4 +1,6 @@
1
- # Validation Helpers
1
+ ---
2
+ title: Validation Helpers
3
+ ---
2
4
 
3
5
  The [`validation_helpers`][validation_helpers] plugin provides helper methods
4
6
  for validating attached files based on extracted metadata.
@@ -7,8 +9,9 @@ for validating attached files based on extracted metadata.
7
9
  plugin :validation_helpers
8
10
 
9
11
  Attacher.validate do
10
- validate_mime_type_inclusion %w[image/jpeg image/png image/gif]
11
- validate_max_size 5*1024*1024 if record.guest?
12
+ validate_mime_type %w[image/jpeg image/png image/webp]
13
+ validate_max_size 5*1024*1024
14
+ # ...
12
15
  end
13
16
  ```
14
17
 
@@ -38,8 +41,8 @@ accept a list of MIME types, and validate that the `mime_type` metadata value
38
41
  is/is not a member of that list.
39
42
 
40
43
  ```rb
41
- validate_mime_type_inclusion %w[image/jpeg image/png image/gif] # file must be a JPEG, PNG or a GIF image
42
- validate_mime_type_exclusion %w[application/x-php] # file must not be a PHP script
44
+ validate_mime_type_inclusion %w[image/jpeg image/png image/webp] # file must be a JPEG, PNG or a WEBP image
45
+ validate_mime_type_exclusion %w[application/x-php] # file must not be a PHP script
43
46
  ```
44
47
 
45
48
  Instead of `#validate_mime_type_inclusion` you can also use just
@@ -52,8 +55,8 @@ accept a list of file extensions, and validate that the `filename` metadata
52
55
  value extension is/is not a member of that list.
53
56
 
54
57
  ```rb
55
- validate_extension_inclusion %w[jpg jpeg png gif] # file must have .jpg, .jpeg, .png, or .gif extension
56
- validate_extension_exclusion %w[php] # file must not have a .php extension
58
+ validate_extension_inclusion %w[jpg jpeg png webp] # file must have .jpg, .jpeg, .png, or .webp extension
59
+ validate_extension_exclusion %w[php] # file must not have a .php extension
57
60
  ```
58
61
 
59
62
  Instead of `#validate_extension_inclusion` you can also use just
@@ -132,7 +135,7 @@ easily do conditional validation:
132
135
 
133
136
  ```rb
134
137
  Attacher.validate do
135
- if validate_mime_type_inclusion %w[image/jpeg image/png image/gif]
138
+ if validate_mime_type_inclusion %w[image/jpeg image/png image/webp]
136
139
  validate_max_width 2000
137
140
  validate_max_height 2000
138
141
  end
@@ -166,8 +169,8 @@ If you would like to change the error message inline, you can pass the
166
169
 
167
170
  ```rb
168
171
  Attacher.validate do
169
- validate_mime_type %w[image/jpeg image/png image/gif], message: "must be JPEG, PNG or GIF"
172
+ validate_mime_type %w[image/jpeg image/png image/webp], message: "must be JPEG, PNG or WEBP"
170
173
  end
171
174
  ```
172
175
 
173
- [validation_helpers]: /lib/shrine/plugins/validation_helpers.rb
176
+ [validation_helpers]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/validation_helpers.rb
@@ -1,4 +1,6 @@
1
- # Versions
1
+ ---
2
+ title: Versions
3
+ ---
2
4
 
3
5
  The [`versions`][versions] plugin enables your uploader to deal with versions,
4
6
  by allowing you to return a Hash of files when processing.
@@ -170,11 +172,5 @@ Attacher.default_url do |options|
170
172
  end
171
173
  ```
172
174
 
173
- ## Re-create Versions
174
-
175
- If you want to re-create a single or all versions, refer to the [reprocessing
176
- versions] guide for details.
177
-
178
- [versions]: /lib/shrine/plugins/versions.rb
179
- [reprocessing versions]: /doc/regenerating_versions.md#readme
175
+ [versions]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/versions.rb
180
176
  [image_processing]: https://github.com/janko/image_processing
@@ -1,4 +1,6 @@
1
- # File Processing
1
+ ---
2
+ title: File Processing
3
+ ---
2
4
 
3
5
  Shrine allows you to process attached files up front or on-the-fly. For
4
6
  example, if your app is accepting image uploads, you can generate a predefined
@@ -53,14 +55,14 @@ class ImageUploader < Shrine
53
55
  end
54
56
  ```
55
57
  ```rb
56
- photo = Photo.new
58
+ photo = Photo.new(image: file)
57
59
  photo.image_derivatives! # calls derivatives processor
58
60
  photo.save
59
61
  ```
60
62
 
61
63
  After the processed files are uploaded, their data is saved into the
62
64
  `<attachment>_data` column. You can then retrieve the derivatives as
63
- [`Shrine::UploadedFile`][uploaded file] objects:
65
+ [`Shrine::UploadedFile`] objects:
64
66
 
65
67
  ```rb
66
68
  photo.image(:large) #=> #<Shrine::UploadedFile ...>
@@ -69,6 +71,21 @@ photo.image(:large).size #=> 5825949
69
71
  photo.image(:large).mime_type #=> "image/jpeg"
70
72
  ```
71
73
 
74
+ ### Automatic processing
75
+
76
+ If you would like derivatives to be automatically created with promotion, you
77
+ can override `Attacher#promote` for call `Attacher#create_derivatives` before
78
+ promotion:
79
+
80
+ ```rb
81
+ class Shrine::Attacher
82
+ def promote(*)
83
+ create_derivatives
84
+ super
85
+ end
86
+ end
87
+ ```
88
+
72
89
  ### Backgrounding
73
90
 
74
91
  Since file processing can be time consuming, it's recommended to move it into a
@@ -341,7 +358,7 @@ to be confused with the [image_optim] gem):
341
358
 
342
359
  ```rb
343
360
  # Gemfile
344
- gem "down", "~> 4.4"
361
+ gem "down", "~> 5.0"
345
362
  gem "http", "~> 4.0"
346
363
  ```
347
364
 
@@ -406,13 +423,14 @@ photo.image_url(width: 100, height: 100, crop: :fit)
406
423
  [Why is libvips quick]: https://github.com/libvips/libvips/wiki/Why-is-libvips-quick
407
424
  [ImageOptim.com]: https://imageoptim.com/api
408
425
  [streamio-ffmpeg]: https://github.com/streamio/streamio-ffmpeg
409
- [Managing Derivatives]: /doc/changing_derivatives.md#readme
426
+ [Managing Derivatives]: https://shrinerb.com/docs/changing-derivatives
410
427
  [Cloudinary]: https://cloudinary.com
411
428
  [shrine-cloudinary]: https://github.com/shrinerb/shrine-cloudinary
412
- [backgrounding]: /doc/plugins/backgrounding.md#readme
429
+ [backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
413
430
  [ruby-vips]: https://github.com/libvips/ruby-vips
414
431
  [MiniMagick]: https://github.com/minimagick/minimagick
415
- [derivation_endpoint]: /doc/plugins/derivation_endpoint.md#readme
416
- [derivation_endpoint performance]: /doc/plugins/derivation_endpoint.md#performance
417
- [derivatives]: /doc/plugins/derivatives.md#readme
432
+ [derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
433
+ [derivation_endpoint performance]: https://shrinerb.com/docs/plugins/derivation_endpoint#performance
434
+ [derivatives]: https://shrinerb.com/docs/plugins/derivatives
418
435
  [concurrent-ruby]: https://github.com/ruby-concurrency/concurrent-ruby
436
+ [image_optim]: https://github.com/toy/image_optim
@@ -1,4 +1,6 @@
1
- # Shrine for Refile Users
1
+ ---
2
+ title: Shrine for Refile Users
3
+ ---
2
4
 
3
5
  This guide is aimed at helping Refile users transition to Shrine, and it consists
4
6
  of three parts:
@@ -7,11 +9,14 @@ of three parts:
7
9
  2. Instructions how to migrate and existing app that uses Refile to Shrine
8
10
  3. Extensive reference of Refile's interface with Shrine equivalents
9
11
 
10
- ## Uploaders
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 representing
14
- uploaded files, similar attachment logic, and direct uploads are also supported.
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,7 +30,7 @@ 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:
@@ -45,38 +50,7 @@ class VideoUploader < Shrine
45
50
  end
46
51
  ```
47
52
 
48
- ### Processing
49
-
50
- Shrine provides on-the-fly processing via the
51
- [`derivation_endpoint`][derivation_endpoint] plugin:
52
-
53
- ```rb
54
- # config/routes.rb (Rails)
55
- Rails.application.routes.draw do
56
- # ...
57
- mount ImageUploader.derivation_endpoint => "/derivations/image"
58
- end
59
- ```
60
- ```rb
61
- require "image_processing/mini_magick"
62
-
63
- class ImageUploader < Shrine
64
- plugin :derivation_endpoint,
65
- secret_key: "<YOUR SECRET KEY>",
66
- prefix: "derivations/image" # needs to match the mount point in routes
67
-
68
- derivation :thumbnail do |file, width, height|
69
- ImageProcessing::MiniMagick
70
- .source(file)
71
- .resize_to_limit!(width.to_i, height.to_i)
72
- end
73
- end
74
- ```
75
-
76
- Shrine also support processing up front using the [`derivatives`][derivatives]
77
- plugin.
78
-
79
- ### URL
53
+ #### URL
80
54
 
81
55
  While Refile serves all files through the Rack endpoint mounted in your app,
82
56
  Shrine serves files directly from storage services:
@@ -93,100 +67,111 @@ If you're using storage which don't expose files over URL (e.g. a database
93
67
  storage), or you want to secure your downloads, you can also serve files
94
68
  through your app using the [`download_endpoint`][download_endpoint] plugin.
95
69
 
96
- ## Attachments
70
+ ### Persistence
71
+
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`
97
79
 
98
- While in Refile you configure attachments by passing options to `.attachment`,
99
- in Shrine you define all your uploading logic inside uploaders, and then
100
- generate an attachment module with that uploader which is included into the
101
- model:
80
+ Shrine, on the other hand, saves all uploaded file data into a single
81
+ `<attachment>_data` column:
102
82
 
103
83
  ```rb
104
- class Photo < Sequel::Model
105
- extend Shrine::Sequel::Attachment
106
- attachment :image, destroy: false
107
- end
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
+ }
108
93
  ```
109
-
110
94
  ```rb
111
- class ImageUploader < Shrine
112
- plugin :sequel
113
- end
95
+ photo.image.id #=> "path/to/image.jpg"
96
+ photo.image.storage_key #=> :store
97
+ photo.image.metadata #=> { "filename" => "...", "size" => ..., "mime_type" => "..." }
114
98
 
115
- class Photo < Sequel::Model
116
- include ImageUploader::Attachment(:image)
117
- end
99
+ photo.image.original_filename #=> "nature.jpg"
100
+ photo.image.size #=> 4739472
101
+ photo.image.mime_type #=> "image/jpeg"
118
102
  ```
119
103
 
120
- This way we can encapsulate all attachment logic inside a class and share it
121
- between different models.
122
-
123
- ### Metadata
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.
124
107
 
125
- Refile allows you to save additional metadata about uploaded files in additional
126
- columns, so you can define `<attachment>_filename`, `<attachment>_content_type`,
127
- or `<attachment>_size`.
108
+ ### Processing
128
109
 
129
- Shrine, on the other hand, saves all metadata into a single `<attachment>_data`
130
- column:
110
+ Shrine provides on-the-fly processing via the
111
+ [`derivation_endpoint`][derivation_endpoint] plugin:
131
112
 
132
113
  ```rb
133
- photo.image_data #=>
134
- # {
135
- # "storage" => "store",
136
- # "id" => "photo/1/image/0d9o8dk42.png",
137
- # "metadata" => {
138
- # "filename" => "nature.png",
139
- # "size" => 49349138,
140
- # "mime_type" => "image/png"
141
- # }
142
- # }
114
+ # config/routes.rb (Rails)
115
+ Rails.application.routes.draw do
116
+ # ...
117
+ mount ImageUploader.derivation_endpoint => "/derivations/image"
118
+ end
119
+ ```
120
+ ```rb
121
+ require "image_processing/mini_magick"
122
+
123
+ class ImageUploader < Shrine
124
+ plugin :derivation_endpoint,
125
+ secret_key: "<YOUR SECRET KEY>",
126
+ prefix: "derivations/image" # needs to match the mount point in routes
143
127
 
144
- photo.image.original_filename #=> "nature.png"
145
- photo.image.size #=> 49349138
146
- photo.image.mime_type #=> "image/png"
128
+ derivation :thumbnail do |file, width, height|
129
+ ImageProcessing::MiniMagick
130
+ .source(file)
131
+ .resize_to_limit!(width.to_i, height.to_i)
132
+ end
133
+ end
147
134
  ```
148
135
 
149
- By default "filename", "size" and "mime_type" is stored, but you can also store
150
- image dimensions, or define any other custom metadata. This also allow storages
151
- to add their own metadata.
136
+ Shrine also support processing up front using the [`derivatives`][derivatives]
137
+ plugin.
152
138
 
153
- ### Validations
139
+ ### Validation
154
140
 
155
- In Refile you define validations by passing options to `.attachment`, while
156
- in Shrine you define validations on the instance-level, which allows them to
157
- be dynamic:
141
+ In Refile, file validation is defined statically on attachment definition:
158
142
 
159
143
  ```rb
160
144
  class Photo < Sequel::Model
161
145
  attachment :image,
162
- extension: %w[jpg jpeg png gif],
163
- content_type: %w[image/jpeg image/png image/gif]
146
+ extension: %w[jpg jpeg png webp],
147
+ content_type: %w[image/jpeg image/png image/webp]
164
148
  end
165
149
  ```
166
150
 
151
+ In Shrine, validation is performed on the instance-level, which allows you to
152
+ make the validation conditional:
153
+
167
154
  ```rb
168
155
  class ImageUploader < Shrine
169
156
  plugin :validation_helpers
170
157
 
171
158
  Attacher.validate do
172
- validate_extension %w[jpg jpeg png gif]
173
- validate_mime_type %w[image/jpeg image/png image/gif]
174
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
175
165
  end
176
166
  end
177
167
  ```
178
168
 
179
169
  Refile extracts the MIME type from the file extension, which means it can
180
170
  easily be spoofed (just give a PHP file a `.jpg` extension). Shrine has the
181
- `determine_mime_type` plugin for determining MIME type from file *content*.
182
-
183
- ### Multiple uploads
184
-
185
- Shrine doesn't have a built-in solution for accepting multiple uploads, but
186
- it's actually very easy to do manually, see the [demo app] on how you can do
187
- multiple uploads directly to S3.
171
+ [`determine_mime_type`][determine_mime_type] plugin for determining MIME type
172
+ from file *content*.
188
173
 
189
- ## Direct uploads
174
+ ### Direct uploads
190
175
 
191
176
  Shrine borrows Refile's idea of direct uploads, and ships with
192
177
  `upload_endpoint` and `presign_endpoint` plugins which provide endpoints for
@@ -200,10 +185,16 @@ Shrine.plugin :upload_endpoint
200
185
  Shrine.presign_endpoint(:cache) # Rack app that generates presigns for specified storage
201
186
  ```
202
187
 
203
- Unlike Refile, Shrine doesn't ship with complete JavaScript which you can just
204
- include to make it work. However, [Uppy] is an excellent JavaScript file upload
205
- library that integrates wonderfully with Shrine, see the [demo app] for a
206
- complete example.
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.
207
198
 
208
199
  ## Migrating from Refile
209
200
 
@@ -260,7 +251,7 @@ class Photo < ActiveRecord::Base
260
251
  include RefileShrineSynchronization
261
252
 
262
253
  before_save do
263
- write_shrine_data(:image) if changes.key?(:image_id)
254
+ write_shrine_data(:image) if image_id_changed?
264
255
  end
265
256
  end
266
257
  ```
@@ -298,8 +289,7 @@ Shrine.storages = {
298
289
 
299
290
  #### `.app`, `.mount_point`, `.automount`
300
291
 
301
- The `upload_endpoint`, `presign_endpoint`, and `derivation_endpoint` plugins
302
- provide methods for generating Rack apps, but you need to mount them
292
+ The Rack apps provided by the `*_endpoint` Shrine plugins are mounted
303
293
  explicitly:
304
294
 
305
295
  ```rb
@@ -312,8 +302,8 @@ end
312
302
 
313
303
  #### `.allow_uploads_to`
314
304
 
315
- The `Shrine.upload_endpoint` and `Shrine.presign_endpoint` require you to
316
- specify the storage that will be used.
305
+ The `Shrine.upload_endpoint` and `Shrine.presign_endpoint` builders require you
306
+ to specify the storage that will be used.
317
307
 
318
308
  #### `.logger`
319
309
 
@@ -335,7 +325,7 @@ end
335
325
 
336
326
  #### `.types`
337
327
 
338
- In Shrine, validations are done by calling `.validate` on the attacher class:
328
+ Shrine defines validations on the uploader class level:
339
329
 
340
330
  ```rb
341
331
  class MyUploader < Shrine
@@ -347,35 +337,38 @@ class MyUploader < Shrine
347
337
  end
348
338
  ```
349
339
 
350
- #### `.extract_filename`, `.extract_content_type`
340
+ #### `.extract_filename`
351
341
 
352
- In Shrine equivalents are (private) methods `Shrine#extract_filename` and
353
- `Shrine#extract_mime_type`.
342
+ Shrine's equivalent is a `Shrine#extract_filename` private method. You can
343
+ instead use the `Shrine#extract_metadata` public method.
354
344
 
355
- #### `.app_url`
345
+ #### `.extract_content_type`
356
346
 
357
- You should use your framework to generate the URL to your mounted direct
358
- endpoint.
347
+ The [`determine_mime_type`][determine_mime_type] plugin provides a
348
+ `Shrine.determine_mime_type` method.
359
349
 
360
- #### `.attachment_url`, `.file_url`
350
+ #### `.app_url`, `.upload_url`, `.attachment_upload_url`, `.presign_url`, `.attachment_presign_url`
361
351
 
362
- You can call `#url` on the uploaded file, or `#<name>_url` on the model.
363
- Additionally you can use the `download_endpoint` plugin.
352
+ Shrine requires you to use your framework to generate URLs to mounted
353
+ endpoints.
364
354
 
365
- #### `.upload_url`, `.attachment_upload_url`, `.presign_url`, `.attachment_presign_url`
355
+ #### `.attachment_url`, `.file_url`
366
356
 
367
- These should be generated directly by you, it depends on where you've mounted
368
- the direct endpoint.
357
+ You can call `#url` on the uploaded file, or `#<name>_url` on the model.
358
+ Alternatively, you can use `#download_url` provided by the `download_endpoint`
359
+ plugin.
369
360
 
370
361
  #### `.host`, `.cdn_host`, `.app_host`, `.allow_downloads_from`, `allow_origin`, `.content_max_age`
371
362
 
372
- Not needed since Shrine doesn't offer on-the-fly processing.
363
+ These can be configured on individual `*_endpoint` plugins.
373
364
 
374
365
  #### `.secret_key`, `.token`, `.valid_token?`
375
366
 
376
- Not needed since Shrine doesn't offer on-the-fly processing.
367
+ The secret key is required for the
368
+ [`derivation_endpoint`][derivation_endpoint], but these methods are not
369
+ exposed.
377
370
 
378
- ### `attachment`
371
+ ### `Attachment`
379
372
 
380
373
  Shrine's equivalent to calling the attachment is including an attachment module
381
374
  of an uploader:
@@ -423,7 +416,7 @@ No equivalent currently exists in Shrine.
423
416
 
424
417
  ### `accepts_attachments_for`
425
418
 
426
- No equivalent in Shrine, but take a look at the "[Multiple Files]" guide.
419
+ No equivalent in Shrine, but take a look at the [Multiple Files] guide.
427
420
 
428
421
  ### Form helpers
429
422
 
@@ -483,11 +476,10 @@ form_for @user do |form|
483
476
  end
484
477
  ```
485
478
 
486
- [image_processing]: https://github.com/janko/image_processing
487
479
  [Uppy]: https://uppy.io
488
- [Direct Uploads to S3]: /doc/direct_s3.md#readme
489
- [demo app]: https://github.com/shrinerb/shrine/tree/master/demo
490
- [Multiple Files]: /doc/multiple_files.md#readme
491
- [derivation_endpoint]: /doc/plugins/derivation_endpoint.md#readme
492
- [download_endpoint]: /doc/plugins/download_endpoint.md#readme
493
- [derivatives]: /doc/plugins/derivatives.md#readme
480
+ [derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
481
+ [download_endpoint]: https://shrinerb.com/docs/plugins/download_endpoint
482
+ [derivatives]: https://shrinerb.com/docs/plugins/derivatives
483
+ [metadata_attributes]: https://shrinerb.com/docs/plugins/metadata_attributes
484
+ [determine_mime_type]: https://shrinerb.com/docs/plugins/determine_mime_type
485
+ [Multiple Files]: https://shrinerb.com/docs/multiple-files