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,9 +1,13 @@
1
- # Advantages of Shrine
1
+ ---
2
+ title: Advantages of Shrine
3
+ ---
2
4
 
3
- There are many existing file upload solutions for Ruby out there [Paperclip],
4
- [CarrierWave], [Dragonfly], [Refile], and [Active Storage], to name the most
5
- popular ones. This guide will attempt to cover some of the main advantages that
6
- Shrine offers compared to these alternatives.
5
+ There are many existing file upload solutions for Ruby out there. This guide
6
+ will attempt to cover some of the main advantages that Shrine offers compared
7
+ to these alternatives.
8
+
9
+ For a more direct comparison with specific file attachment libraries, there are
10
+ more specialized guides for [CarrierWave], [Paperclip], and [Refile] users.
7
11
 
8
12
  ## Generality
9
13
 
@@ -11,15 +15,15 @@ Many alternative file upload solutions are coupled to either Rails (Active
11
15
  Storage) or Active Record itself (Paperclip, Dragonfly). This is not ideal, as
12
16
  Rails-specific solutions fragment the Ruby community between developers that
13
17
  use Rails and developers that don't. There are many great web frameworks
14
- ([Sinatra], [Roda], [Cuba], [Hanami], [Grape]) and database libraries
15
- ([Sequel], [ROM], [Hanami::Model]) out there that people use instead of
16
- Rails and Active Record.
18
+ ([Sinatra], [Roda], [Cuba], [Hanami], [Grape]) and persistence libraries
19
+ ([Sequel], [ROM], [Hanami::Model]) out there that people use instead of Rails
20
+ and Active Record.
17
21
 
18
22
  Shrine, on the other hand, doesn't make any assumptions about which web
19
- framework or ORM you're using. Any web-specific functionality is implemented
20
- on top of [Rack], the Ruby web server interface that powers all the popular
21
- Ruby web frameworks (including Rails). The integrations for specific ORMs are
22
- provided as plugins.
23
+ framework or persistence library you're using. Any web-specific functionality
24
+ is implemented on top of [Rack], the Ruby web server interface that powers all
25
+ the popular Ruby web frameworks (including Rails). The integrations for
26
+ specific ORMs are provided as plugins.
23
27
 
24
28
  ```rb
25
29
  # Rack-based plugins
@@ -34,51 +38,57 @@ Shrine.plugin :rack_file
34
38
  Shrine.plugin :activerecord
35
39
  Shrine.plugin :sequel
36
40
  Shrine.plugin :mongoid # https://github.com/shrinerb/shrine-mongoid
41
+ Shrine.plugin :rom # https://github.com/shrinerb/shrine-rom
37
42
  Shrine.plugin :hanami # https://github.com/katafrakt/hanami-shrine
38
43
  ```
39
44
 
40
45
  ## Simplicity
41
46
 
42
47
  Where some popular file attachment libraries have [god objects]
43
- (`CarrierWave::Uploader::Base` and `Paperclip::Attachment`), Shrine has several
44
- core classes, each with a clear set of responsibilities:
48
+ (`CarrierWave::Uploader::Base` and `Paperclip::Attachment`), Shrine distributes
49
+ responsibilities across multiple core classes:
45
50
 
46
- * Storage classes encapsulate file operations for the underlying service
47
- * `Shrine` handles uploads and manages plugins
48
- * `Shrine::UploadedFile` repesents a file that was uploaded to a storage
49
- * `Shrine::Attacher` handles attaching files to records
50
- * `Shrine::Attachment` adds convenience methods to model instances
51
+ | Class | Description |
52
+ | :---- | :----------- |
53
+ | `Shrine::Storage::*` | Encapsulate file operations for the underlying service |
54
+ | `Shrine` | Wraps uploads and handles loading plugins |
55
+ | `Shrine::UploadedFile` | Represents a file that was uploaded to a storage |
56
+ | `Shrine::Attacher` | Handles attaching files to records |
57
+ | `Shrine::Attachment` | Adds convenience attachment methods to model instances |
51
58
 
52
59
  ```rb
53
- photo.image #=> #<Shrine::UploadedFile>
54
- photo.image.storage #=> #<Shrine::Storage::S3>
55
- photo.image.uploader #=> #<Shrine>
56
- photo.image_attacher #=> #<Shrine::Attacher>
60
+ photo.image #=> #<Shrine::UploadedFile>
61
+ photo.image.storage #=> #<Shrine::Storage::S3>
62
+ photo.image.uploader #=> #<Shrine>
63
+ photo.image_attacher #=> #<Shrine::Attacher>
64
+ photo.class.ancestors #=> [..., #<Shrine::Attachment(:image)>, ...]
57
65
  ```
58
66
 
59
67
  The attachment functionality is decoupled from persistence and storage, which
60
68
  makes it much easier to reason about. Also, special care was taken to make
61
- integrating new storages and ORMs possible with minimal amount of code.
69
+ integrating new storages and persistence libraries as easy as possible.
62
70
 
63
71
  ## Modularity
64
72
 
65
73
  Shrine uses a [plugin system] that allows you to pick and choose the features
66
74
  that you want. Moreover, you'll only be loading code for the features you've
67
- selected, which means that Shrine will generally much faster than the
75
+ selected, which means that Shrine will generally load much faster than the
68
76
  alternatives.
69
77
 
70
78
  ```rb
71
79
  Shrine.plugin :instrumentation
72
80
 
73
- # translates to
81
+ # which translates to
74
82
 
75
83
  require "shrine/plugins/instrumentation"
76
84
  Shrine.plugin Shrine::Plugins::Instrumentation
77
85
  ```
86
+ ```rb
87
+ Shrine.method(:instrument).owner #=> Shrine::Plugins::Instrumentation::ClassMethods
88
+ ```
78
89
 
79
90
  Shrine recommends a certain type of attachment flow, but it still offers good
80
- low-level abstractions that give you the flexibility to build your own
81
- attachment flow.
91
+ low-level abstractions that give you the flexibility to build your own flow.
82
92
 
83
93
  ```rb
84
94
  uploaded_file = ImageUploader.upload(image, :store) # metadata extraction, upload location generation
@@ -113,9 +123,6 @@ Shrine.plugin :determine_mime_type, analyzer: :marcel
113
123
  Shrine.plugin :store_dimensions, analyzer: :mini_magick
114
124
  ```
115
125
 
116
- This approach gives you control over your dependencies by allowing you to
117
- choose the combination that best suits your needs.
118
-
119
126
  ## Inheritance
120
127
 
121
128
  Shrine is designed to handle any types of files. If you're accepting uploads of
@@ -126,9 +133,9 @@ for handling them will differ:
126
133
  * you might want to store different files to different storage services (images, documents, audios, videos)
127
134
  * extracting metadata might require different tools depending on the filetype
128
135
 
129
- With Shrine you can create isolated uploaders for each type of file. Plugins
130
- that you want to be applied to all uploaders can be applied globally, while
131
- other plugins would be loaded only for a specific uploader.
136
+ With Shrine you can create isolated uploaders for each type of file. For
137
+ features you want all uploaders to share, their plugins can be loaded globally,
138
+ while other plugins you can load only for selected uploaders.
132
139
 
133
140
  ```rb
134
141
  # loaded for all plugins
@@ -150,18 +157,17 @@ end
150
157
 
151
158
  ## Processing
152
159
 
153
- Most file attachment libraries give you the ability to process files either "on
154
- attachment" (Paperclip, CarrierWave) or "on-the-fly" (Dragonfly, Refile, Active
155
- Storage). However, you should ideally be able to choose both, because both
156
- approaches have their pros and cons. For example, on-the-fly processing is only
157
- suitable for fast processing (image thumbnails, document previews), longer
158
- running processing should be moved into a background job (video transcoding,
159
- raw images).
160
+ Most file attachment libraries provide either processing files up front
161
+ (Paperclip, CarrierWave) or on-the-fly (Dragonfly, Refile, Active Storage).
162
+ However, each approach is suitable for different requirements. For instance,
163
+ while on-the-fly processing is suitable for fast processing (image thumbnails,
164
+ document previews), longer running processing (video transcoding, raw images)
165
+ should be moved into a background job.
160
166
 
161
- Shrine is the first file attachment library that has support for both
162
- processing on attachment and on-the-fly. So, if you're handling image uploads,
163
- you can choose to either generate a set of pre-defined image thumbnails in a
164
- background job:
167
+ That's why Shrine supports both [up front][derivatives] and
168
+ [on-the-fly][derivation_endpoint] processing. For example, if you're handling
169
+ image uploads, you can choose to either generate a set of pre-defined
170
+ thumbnails during attachment:
165
171
 
166
172
  ```rb
167
173
  class ImageUploader < Shrine
@@ -177,8 +183,8 @@ class ImageUploader < Shrine
177
183
  end
178
184
  ```
179
185
  ```rb
180
- photo.image_url(:large)
181
- #=> "https://s3.amazonaws.com/path/to/large.jpg"
186
+ photo.image_derivatives! # creates thumbnails
187
+ photo.image_url(:large) #=> "https://s3.amazonaws.com/path/to/large.jpg"
182
188
  ```
183
189
 
184
190
  or generate thumbnails on-demand:
@@ -197,42 +203,43 @@ photo.image.derivation_url(:thumbnail, 600, 400)
197
203
  #=> ".../thumbnail/600/400/eyJpZCI6ImZvbyIsInN0b3JhZ2UiOiJzdG9yZSJ9?signature=..."
198
204
  ```
199
205
 
200
- ### Image processing
206
+ ### ImageMagick
201
207
 
202
208
  Many file attachment libraries, such as CarrierWave, Paperclip, Dragonfly and
203
- Refile, implement their own image processing macros. Instead of creating
204
- yet another in-house implementation, the **[ImageProcessing]** gem was created.
205
-
206
- While the ImageProcessing gem was created for Shrine, it's completely generic
207
- and can be used standalone or with any other file upload library (e.g. Active
208
- Storage 6+ uses it). It takes care of many details for you, such as [auto
209
- orienting] the input image and [sharpening] the thumbnails after they are
210
- resized.
209
+ Refile, implement their own image processing macros. Rather than building yet
210
+ another in-house implementation, a general purpose **[ImageProcessing]** gem
211
+ was created instead, which works great with Shrine.
211
212
 
212
213
  ```rb
213
- require "image_processing"
214
+ require "image_processing/mini_magick"
214
215
 
215
216
  thumbnail = ImageProcessing::MiniMagick
216
217
  .source(image)
217
218
  .resize_to_limit(400, 400)
218
219
  .call # convert input.jpg -auto-orient -resize 400x400> -sharpen 0x1 output.jpg
219
220
 
220
- thumbnail #=> #<Tempfile:/var/folders/.../image_processing20180316-18446-1j247h6.png>
221
+ thumbnail #=> #<Tempfile:/var/folders/.../image_processing20180316-18446-1j247h6.jpg>
221
222
  ```
222
223
 
223
- #### libvips
224
+ It takes care of many details for you, such as [auto orienting] the input image
225
+ and applying [sharpening] to resized images. It also has support for
226
+ [libvips](#libvips).
227
+
228
+ ### libvips
224
229
 
225
- Probably the biggest ImageProcessing feature is the support for **[libvips]**.
226
- libvips is a full-featured image processing library like ImageMagick, with
227
- impressive performance characteristics it's often **multiple times faster**
228
- than ImageMagick and has low memory usage (see [Why is libvips quick]).
230
+ **[libvips]** is a full-featured image processing library like ImageMagick,
231
+ with [great performance characteristics][libvips performance]. It's often
232
+ **multiple times faster** than ImageMagick, and also has lower memory usage.
233
+ For more details, see [Why is libvips quick].
229
234
 
230
- The `ImageProcessing::Vips` backend implements the same API as
231
- `ImageProcessing::MiniMagick`, so you can easily swap one for the other.
235
+ The ImageProcessing gem provides libvips support as an alternative
236
+ `ImageProcessing::Vips` backend, sharing the same API as the
237
+ `ImageProcessing::MiniMagick` backend.
232
238
 
233
239
  ```rb
234
240
  require "image_processing/vips"
235
241
 
242
+ # this now generates the thumbnail using libvips
236
243
  ImageProcessing::Vips
237
244
  .source(image)
238
245
  .resize_to_limit!(400, 400)
@@ -240,13 +247,18 @@ ImageProcessing::Vips
240
247
 
241
248
  ### Other processors
242
249
 
243
- Both processing "on upload" and "on-the-fly" work in a way that you define a
244
- Ruby block, which accepts a source file and is expected to return a processed
245
- file. How you're going to do the processing is entirely up to you.
250
+ In contrast to most file attachment libraries, file processing in Shrine is
251
+ just a functional transformation, where you receive the source file on the
252
+ input and return processed files on the output. This makes it easier to use
253
+ custom processing tools and encourages building generic processors that can be
254
+ reused outside of Shrine.
246
255
 
247
- This allows you to use any tool you want. For example, you could implement
248
- video transcoding:
256
+ Here is an example of transcoding videos using the [streamio-ffmpeg] gem:
249
257
 
258
+ ```rb
259
+ # Gemfile
260
+ gem "streamio-ffmpeg"
261
+ ```
250
262
  ```rb
251
263
  class VideoUploader < Shrine
252
264
  Attacher.derivatives_processor do |original|
@@ -261,6 +273,13 @@ class VideoUploader < Shrine
261
273
  end
262
274
  end
263
275
  ```
276
+ ```rb
277
+ movie.video_derivatives! # create derivatives
278
+
279
+ movie.video #=> #<Shrine::UploadedFile @id="5a5cd0.mov" ...>
280
+ movie.video(:transcoded) #=> #<Shrine::UploadedFile @id="7481d6.mp4" ...>
281
+ movie.video(:screenshot) #=> #<Shrine::UploadedFile @id="8f3136.jpg" ...>
282
+ ```
264
283
 
265
284
  ## Metadata & Validation
266
285
 
@@ -302,13 +321,14 @@ end
302
321
 
303
322
  ## Backgrounding
304
323
 
305
- In most file upload solutions background processing was an afterthought, which
306
- resulted in complex implementations. Shrine was designed with backgrounding
307
- feature in mind from day one. It is supported via the
308
- [`backgrounding`][backgrounding] plugin and can be used with [any backgrounding
309
- library][backgrounding libraries].
324
+ In most file upload solutions, support for background processing was an
325
+ afterthought, which resulted in complex and unreliable implementations. Shrine
326
+ was designed with backgrounding feature in mind from day one. It is supported
327
+ via the [`backgrounding`][backgrounding] plugin and can be used with [any
328
+ backgrounding library][backgrounding libraries].
310
329
 
311
330
  ```rb
331
+ Shrine.plugin :backgrounding
312
332
  Shrine::Attacher.promote_block do
313
333
  PromoteJob.perform_async(self.class.name, record.class.name, record.id, name, file_data)
314
334
  end
@@ -324,68 +344,47 @@ class PromoteJob
324
344
  attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
325
345
  attacher.create_derivatives # perform processing
326
346
  attacher.atomic_promote
347
+ rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
348
+ # attachment changes are detected for concurrency safety
327
349
  end
328
350
  end
329
351
  ```
330
352
 
353
+ With Shrine, there is no need for a separate boolean column that indicates the
354
+ processing status. Processed file data is stored into the attachment database
355
+ column, which allows you to easily check whether a file has been processed.
356
+
357
+ ```rb
358
+ photo = Photo.create(image: file) # background job is kicked off
359
+
360
+ photo.image(:large) #=> nil (thumbnails are still being processed)
361
+ # ... sometime later ...
362
+ photo.image(:large) #=> #<Shrine::UploadedFile> (processing has finished)
363
+ ```
364
+
331
365
  ## Direct Uploads
332
366
 
333
- Shrine doesn't come with a plug-and-play JavaScript solution for client-side
334
- uploads like Refile and Active Storage, but instead it adopts **[Uppy]**. Uppy
335
- is a modern JavaScript file upload library, which offers support for uploading
336
- to [AWS S3][Uppy AwsS3], to a [custom endpoint][Uppy XHRUpload], or even to a
337
- [resumable endpoint][Uppy Tus]. It comes with a set of UI components, ranging
338
- from a simple [status bar][Uppy StatusBar] to a full-featured [dashboard][Uppy
339
- Dashboard]. Since Uppy is maintained by the wide JavaScript community, it's
340
- generally a better choice than any homegrown solution.
341
-
342
- Shrine provides Rack components for uploads that integrate nicely with Uppy.
343
- So, whether you want Uppy to upload directly [to your app][upload_endpoint], or
344
- you want to authorize direct uploads [to the cloud][presign_endpoint], Shrine
345
- has it streamlined.
346
-
347
- ### Resumable uploads
348
-
349
- If your users are uploading large files, flaky internet connections can cause
350
- uploads to fail halfway, which can be a frustrating user experience. To fix
351
- this problem, [Transloadit] company has created an open HTTP-based protocol for
352
- resumable uploads **[tus]**. There are already countless client and server
353
- [implementations][tus implementations] of the protocol in various languages.
354
-
355
- So, if you're expecting large file uploads, you can use Uppy as a [JavaScript
356
- client][Uppy Tus] and have it upload to [Ruby server][tus-ruby-server], then
357
- attach uploaded files using the handy [Shrine integration][shrine-tus]. Shrine
358
- handles uploads and downloads in a streaming fashion, so you can expect low
359
- memory usage.
360
-
361
- Alternatively, you can have [resumable multipart uploads directly to
362
- S3][uppy-s3_multipart].
363
-
364
- ## Summary
365
-
366
- Shrine is general purpose, it can integrate with any web framework and any
367
- database library. It has core classes with clearly defined responsibilities,
368
- which provide both higher and lower level abstractions. The functionality is
369
- very modular, you can pick and choose features that you need.
370
-
371
- With Shrine you can process both on attachment and on-the-fly, depending on
372
- what is more suitable for your requirements. Processing is just a functional
373
- transformation, which makes it easier to use the processing tool of your
374
- choice. You can also move processing into a background job.
375
-
376
- Shrine automatically extracts metadata from the main file and any processed
377
- files. In addition to built-in metadata you can also extract any custom
378
- metadata. Any extracted metadata can be validated on attachment.
379
-
380
- Finally, Shrine integrates with Uppy, a full-featured JavaScript file upload
381
- library. It allows you to do direct uploads to your app or to S3. For large
382
- files you can also make the uploads resumable.
383
-
384
- [Paperclip]: https://github.com/thoughtbot/paperclip
385
- [CarrierWave]: https://github.com/carrierwaveuploader/carrierwave
386
- [Dragonfly]: http://markevans.github.io/dragonfly/
387
- [Refile]: https://github.com/refile/refile
388
- [Active Storage]: https://github.com/rails/rails/tree/master/activestorage#active-storage
367
+ For client side uploads, Shrine adopts **[Uppy]**, a modern JavaScript file
368
+ upload library. This gives the developer a lot more power in customizing the
369
+ user experience compared to a custom JavaScript solution implemented by Refile
370
+ and Active Storage.
371
+
372
+ Uppy supports direct uploads to [AWS S3][Uppy AwsS3] or to a [custom
373
+ endpoint][Uppy XHRUpload]. It also supports **resumable** uploads, either
374
+ [directly to S3][Uppy AwsS3Multipart] or via the [tus protocol][tus]. For the
375
+ UI you can choose from various components, ranging from a simple [status
376
+ bar][Uppy StatusBar] to a full-featured [dashboard][Uppy Dashboard].
377
+
378
+ Shrine provides server side components for each type of upload. They are built
379
+ on top of Rack, so that they can be used with any Ruby web framework.
380
+
381
+ | Uppy | Shrine |
382
+ | :--- | :----- |
383
+ | [XHRUpload][Uppy XHRUpload] | [`upload_endpoint`][upload_endpoint] |
384
+ | [AwsS3][Uppy AwsS3] | [`presign_endpoint`][presign_endpoint] |
385
+ | [AwsS3Multipart][Uppy AwsS3Multipart] | [`uppy-s3_multipart`][uppy-s3_multipart] |
386
+ | [Tus][Uppy Tus] | [`tus-ruby-server`][tus-ruby-server] |
387
+
389
388
  [Rack]: https://rack.github.io
390
389
  [Sinatra]: http://sinatrarb.com
391
390
  [Roda]: http://roda.jeremyevans.net
@@ -408,32 +407,36 @@ files you can also make the uploads resumable.
408
407
  [MiniMagick]: https://github.com/minimagick/minimagick
409
408
  [ruby-vips]: https://github.com/libvips/ruby-vips
410
409
  [god objects]: https://en.wikipedia.org/wiki/God_object
411
- [ImageMagick]: https://www.imagemagick.org
412
410
  [ImageProcessing]: https://github.com/janko/image_processing
413
411
  [auto orienting]: https://www.imagemagick.org/script/command-line-options.php#auto-orient
414
412
  [sharpening]: https://photography.tutsplus.com/tutorials/what-is-image-sharpening--cms-26627
415
413
  [libvips]: http://libvips.github.io/libvips/
416
414
  [Why is libvips quick]: https://github.com/libvips/libvips/wiki/Why-is-libvips-quick
417
- [metadata]: /doc/metadata.md#readme
418
- [store_dimensions]: /doc/plugins/store_dimensions.md#readme
419
- [add_metadata]: /doc/plugins/add_metadata.md#readme
420
- [validation]: /doc/validation.md#readme
421
- [upload_endpoint]: /doc/plugins/upload_endpoint.md#readme
422
- [presign_endpoint]: /doc/plugins/presign_endpoint.md#readme
415
+ [metadata]: https://shrinerb.com/docs/metadata
416
+ [store_dimensions]: https://shrinerb.com/docs/plugins/store_dimensions
417
+ [add_metadata]: https://shrinerb.com/docs/plugins/add_metadata
418
+ [validation]: https://shrinerb.com/docs/validation
419
+ [upload_endpoint]: https://shrinerb.com/docs/plugins/upload_endpoint
420
+ [presign_endpoint]: https://shrinerb.com/docs/plugins/presign_endpoint
423
421
  [Uppy]: https://uppy.io
424
- [Uppy XHRUpload]: https://uppy.io/docs/xhrupload/
422
+ [Uppy XHRUpload]: https://uppy.io/docs/xhr-upload/
425
423
  [Uppy AwsS3]: https://uppy.io/docs/aws-s3/
426
424
  [Uppy Tus]: https://uppy.io/docs/tus/
425
+ [Uppy AwsS3Multipart]: https://uppy.io/docs/aws-s3-multipart/
426
+ [tus]: https://tus.io
427
427
  [Uppy StatusBar]: https://uppy.io/examples/statusbar/
428
428
  [Uppy Dashboard]: https://uppy.io/examples/dashboard/
429
- [backgrounding]: /doc/plugins/backgrounding.md#readme
430
- [backgrounding libraries]: https://github.com/shrinerb/shrine/wiki/Backgrounding-Libraries
431
- [Down streaming]: https://github.com/janko/down#streaming
432
- [Transloadit]: https://transloadit.com
433
- [tus]: https://tus.io
434
- [tus implementations]: https://tus.io/implementations.html
435
429
  [tus-ruby-server]: https://github.com/janko/tus-ruby-server
436
- [shrine-tus]: https://github.com/shrinerb/shrine-tus
437
430
  [uppy-s3_multipart]: https://github.com/janko/uppy-s3_multipart
438
- [validation_helpers]: /doc/plugins/validation_helpers.md#readme
439
- [custom validations]: /doc/validation.md#custom-validations
431
+ [backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
432
+ [backgrounding libraries]: https://github.com/shrinerb/shrine/wiki/Backgrounding-Libraries
433
+ [Down streaming]: https://github.com/janko/down#streaming
434
+ [validation_helpers]: https://shrinerb.com/docs/plugins/validation_helpers
435
+ [custom validations]: https://shrinerb.com/docs/validation#custom-validations
436
+ [derivatives]: https://shrinerb.com/docs/plugins/derivatives
437
+ [derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
438
+ [libvips performance]: https://github.com/libvips/libvips/wiki/Speed-and-memory-use#results
439
+ [streamio-ffmpeg]: https://github.com/streamio/streamio-ffmpeg
440
+ [CarrierWave]: https://shrinerb.com/docs/carrierwave
441
+ [Paperclip]: https://shrinerb.com/docs/paperclip
442
+ [Refile]: https://shrinerb.com/docs/refile
@@ -1,27 +1,9 @@
1
- # Using Attacher
1
+ ---
2
+ title: Using Attacher
3
+ ---
2
4
 
3
5
  This guide explains what is `Shrine::Attacher` and how to use it.
4
6
 
5
- ## Contents
6
-
7
- * [Introduction](#introduction)
8
- * [Storage](#storage)
9
- * [Attaching](#attaching)
10
- - [Attaching cached](#attaching-cached)
11
- - [Attaching stored](#attaching-stored)
12
- - [Uploading](#uploading)
13
- - [Changes](#changes)
14
- * [Finalizing](#finalizing)
15
- - [Promoting](#promoting)
16
- - [Replacing](#replacing)
17
- * [Retrieving](#retreiving)
18
- - [File](#file)
19
- - [Attached](#attached)
20
- - [URL](#url)
21
- - [Data](#data)
22
- * [Deleting](#deleting)
23
- * [Context](#context)
24
-
25
7
  ## Introduction
26
8
 
27
9
  The attachment logic is handled by a `Shrine::Attacher` object. The
@@ -47,10 +29,10 @@ attacher.file # called by `photo.image`
47
29
  attacher.url # called by `photo.image_url`
48
30
  ```
49
31
 
50
- The `model`, `entity`, and `column` plugins provide additional
51
- `Shrine::Attacher` methods (such as `Shrine::Attacher.from_model` we see
52
- above), but in this guide we'll focus only on the core `Shrine::Attacher`
53
- methods.
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.
54
36
 
55
37
  So, we'll assume a `Shrine::Attacher` object not backed by any model/entity:
56
38
 
@@ -446,8 +428,8 @@ However, it's generally better practice to pass uploader options directly to
446
428
  `Attacher#assign`, `Attacher#attach`, `Attacher#promote` or any other method
447
429
  that's calling `Attacher#upload`.
448
430
 
449
- [validation]: /doc/plugins/validation.md#readme
450
- [column]: /doc/plugins/column.md#readme
451
- [entity]: /doc/plugins/entity.md#readme
452
- [model]: /doc/plugins/model.md#readme
453
- [backgrounding]: /doc/plugins/backgrounding.md#readme
431
+ [validation]: https://shrinerb.com/docs/plugins/validation
432
+ [column]: https://shrinerb.com/docs/plugins/column
433
+ [entity]: https://shrinerb.com/docs/plugins/entity
434
+ [model]: https://shrinerb.com/docs/plugins/model
435
+ [backgrounding]: https://shrinerb.com/docs/plugins/backgrounding