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.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +523 -41
  3. data/LICENSE.txt +1 -1
  4. data/README.md +83 -979
  5. data/doc/advantages.md +231 -204
  6. data/doc/attacher.md +304 -153
  7. data/doc/carrierwave.md +297 -226
  8. data/doc/changing_derivatives.md +308 -0
  9. data/doc/changing_location.md +103 -21
  10. data/doc/changing_storage.md +110 -0
  11. data/doc/creating_persistence_plugins.md +132 -0
  12. data/doc/creating_plugins.md +43 -23
  13. data/doc/creating_storages.md +19 -5
  14. data/doc/design.md +147 -97
  15. data/doc/direct_s3.md +38 -28
  16. data/doc/external/articles.md +63 -0
  17. data/doc/external/extensions.md +53 -0
  18. data/doc/external/misc.md +32 -0
  19. data/doc/getting_started.md +1156 -0
  20. data/doc/metadata.md +190 -109
  21. data/doc/multiple_files.md +93 -30
  22. data/doc/paperclip.md +384 -262
  23. data/doc/plugins/activerecord.md +177 -46
  24. data/doc/plugins/add_metadata.md +139 -38
  25. data/doc/plugins/atomic_helpers.md +217 -0
  26. data/doc/plugins/backgrounding.md +156 -98
  27. data/doc/plugins/cached_attachment_data.md +7 -5
  28. data/doc/plugins/column.md +121 -0
  29. data/doc/plugins/data_uri.md +23 -22
  30. data/doc/plugins/default_storage.md +36 -10
  31. data/doc/plugins/default_url.md +30 -13
  32. data/doc/plugins/delete_raw.md +4 -2
  33. data/doc/plugins/derivation_endpoint.md +186 -101
  34. data/doc/plugins/derivatives.md +839 -0
  35. data/doc/plugins/determine_mime_type.md +4 -2
  36. data/doc/plugins/download_endpoint.md +64 -8
  37. data/doc/plugins/dynamic_storage.md +5 -3
  38. data/doc/plugins/entity.md +263 -0
  39. data/doc/plugins/form_assign.md +55 -0
  40. data/doc/plugins/included.md +31 -8
  41. data/doc/plugins/infer_extension.md +21 -10
  42. data/doc/plugins/instrumentation.md +38 -16
  43. data/doc/plugins/keep_files.md +16 -17
  44. data/doc/plugins/metadata_attributes.md +42 -13
  45. data/doc/plugins/mirroring.md +118 -0
  46. data/doc/plugins/model.md +210 -0
  47. data/doc/plugins/module_include.md +4 -2
  48. data/doc/plugins/multi_cache.md +24 -0
  49. data/doc/plugins/persistence.md +101 -0
  50. data/doc/plugins/presign_endpoint.md +9 -4
  51. data/doc/plugins/pretty_location.md +16 -3
  52. data/doc/plugins/processing.md +4 -2
  53. data/doc/plugins/rack_file.md +8 -2
  54. data/doc/plugins/rack_response.md +6 -2
  55. data/doc/plugins/recache.md +4 -2
  56. data/doc/plugins/refresh_metadata.md +49 -9
  57. data/doc/plugins/remote_url.md +84 -47
  58. data/doc/plugins/remove_attachment.md +27 -6
  59. data/doc/plugins/remove_invalid.md +21 -6
  60. data/doc/plugins/restore_cached_data.md +11 -3
  61. data/doc/plugins/sequel.md +159 -35
  62. data/doc/plugins/signature.md +16 -5
  63. data/doc/plugins/store_dimensions.md +14 -2
  64. data/doc/plugins/tempfile.md +4 -2
  65. data/doc/plugins/type_predicates.md +96 -0
  66. data/doc/plugins/upload_endpoint.md +13 -13
  67. data/doc/plugins/upload_options.md +6 -4
  68. data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
  69. data/doc/plugins/validation.md +97 -0
  70. data/doc/plugins/validation_helpers.md +16 -13
  71. data/doc/plugins/versions.md +15 -19
  72. data/doc/processing.md +438 -221
  73. data/doc/refile.md +188 -170
  74. data/doc/release_notes/1.0.0.md +4 -0
  75. data/doc/release_notes/1.1.0.md +6 -2
  76. data/doc/release_notes/1.2.0.md +4 -0
  77. data/doc/release_notes/1.3.0.md +4 -0
  78. data/doc/release_notes/1.4.0.md +4 -0
  79. data/doc/release_notes/1.4.1.md +4 -0
  80. data/doc/release_notes/1.4.2.md +4 -0
  81. data/doc/release_notes/2.0.0.md +4 -0
  82. data/doc/release_notes/2.0.1.md +4 -0
  83. data/doc/release_notes/2.1.0.md +5 -1
  84. data/doc/release_notes/2.1.1.md +4 -0
  85. data/doc/release_notes/2.10.0.md +4 -0
  86. data/doc/release_notes/2.10.1.md +4 -0
  87. data/doc/release_notes/2.11.0.md +4 -0
  88. data/doc/release_notes/2.12.0.md +4 -0
  89. data/doc/release_notes/2.13.0.md +4 -0
  90. data/doc/release_notes/2.14.0.md +5 -1
  91. data/doc/release_notes/2.15.0.md +11 -7
  92. data/doc/release_notes/2.16.0.md +4 -0
  93. data/doc/release_notes/2.17.0.md +4 -0
  94. data/doc/release_notes/2.18.0.md +4 -0
  95. data/doc/release_notes/2.19.0.md +6 -3
  96. data/doc/release_notes/2.2.0.md +4 -0
  97. data/doc/release_notes/2.3.0.md +4 -0
  98. data/doc/release_notes/2.3.1.md +4 -0
  99. data/doc/release_notes/2.4.0.md +4 -0
  100. data/doc/release_notes/2.4.1.md +4 -0
  101. data/doc/release_notes/2.5.0.md +4 -0
  102. data/doc/release_notes/2.6.0.md +4 -0
  103. data/doc/release_notes/2.6.1.md +4 -0
  104. data/doc/release_notes/2.7.0.md +4 -0
  105. data/doc/release_notes/2.8.0.md +4 -0
  106. data/doc/release_notes/2.9.0.md +4 -0
  107. data/doc/release_notes/3.0.0.md +981 -0
  108. data/doc/release_notes/3.0.1.md +22 -0
  109. data/doc/release_notes/3.1.0.md +73 -0
  110. data/doc/release_notes/3.2.0.md +96 -0
  111. data/doc/release_notes/3.2.1.md +31 -0
  112. data/doc/release_notes/3.2.2.md +14 -0
  113. data/doc/release_notes/3.3.0.md +105 -0
  114. data/doc/release_notes/3.4.0.md +35 -0
  115. data/doc/release_notes/3.5.0.md +63 -0
  116. data/doc/release_notes/3.6.0.md +23 -0
  117. data/doc/retrieving_uploads.md +5 -2
  118. data/doc/securing_uploads.md +60 -37
  119. data/doc/storage/file_system.md +20 -3
  120. data/doc/storage/memory.md +19 -0
  121. data/doc/storage/s3.md +122 -78
  122. data/doc/testing.md +141 -133
  123. data/doc/upgrading_to_3.md +708 -0
  124. data/doc/validation.md +54 -90
  125. data/lib/shrine/attacher.rb +292 -169
  126. data/lib/shrine/attachment.rb +13 -46
  127. data/lib/shrine/plugins/_persistence.rb +93 -0
  128. data/lib/shrine/plugins/activerecord.rb +77 -34
  129. data/lib/shrine/plugins/add_metadata.rb +25 -17
  130. data/lib/shrine/plugins/atomic_helpers.rb +119 -0
  131. data/lib/shrine/plugins/backgrounding.rb +77 -113
  132. data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
  133. data/lib/shrine/plugins/column.rb +102 -0
  134. data/lib/shrine/plugins/data_uri.rb +38 -36
  135. data/lib/shrine/plugins/default_storage.rb +45 -15
  136. data/lib/shrine/plugins/default_url.rb +12 -24
  137. data/lib/shrine/plugins/default_url_options.rb +3 -30
  138. data/lib/shrine/plugins/delete_raw.rb +10 -16
  139. data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
  140. data/lib/shrine/plugins/derivatives.rb +645 -0
  141. data/lib/shrine/plugins/determine_mime_type.rb +9 -21
  142. data/lib/shrine/plugins/download_endpoint.rb +118 -133
  143. data/lib/shrine/plugins/dynamic_storage.rb +5 -11
  144. data/lib/shrine/plugins/entity.rb +158 -0
  145. data/lib/shrine/plugins/form_assign.rb +108 -0
  146. data/lib/shrine/plugins/included.rb +6 -6
  147. data/lib/shrine/plugins/infer_extension.rb +17 -20
  148. data/lib/shrine/plugins/instrumentation.rb +59 -43
  149. data/lib/shrine/plugins/keep_files.rb +3 -15
  150. data/lib/shrine/plugins/metadata_attributes.rb +28 -19
  151. data/lib/shrine/plugins/mirroring.rb +142 -0
  152. data/lib/shrine/plugins/model.rb +160 -0
  153. data/lib/shrine/plugins/module_include.rb +3 -3
  154. data/lib/shrine/plugins/multi_cache.rb +27 -0
  155. data/lib/shrine/plugins/presign_endpoint.rb +27 -28
  156. data/lib/shrine/plugins/pretty_location.rb +15 -9
  157. data/lib/shrine/plugins/processing.rb +22 -9
  158. data/lib/shrine/plugins/rack_file.rb +2 -42
  159. data/lib/shrine/plugins/rack_response.rb +21 -10
  160. data/lib/shrine/plugins/recache.rb +6 -5
  161. data/lib/shrine/plugins/refresh_metadata.rb +13 -11
  162. data/lib/shrine/plugins/remote_url.rb +49 -49
  163. data/lib/shrine/plugins/remove_attachment.rb +12 -6
  164. data/lib/shrine/plugins/remove_invalid.rb +19 -8
  165. data/lib/shrine/plugins/restore_cached_data.rb +13 -7
  166. data/lib/shrine/plugins/sequel.rb +86 -36
  167. data/lib/shrine/plugins/signature.rb +10 -16
  168. data/lib/shrine/plugins/store_dimensions.rb +35 -40
  169. data/lib/shrine/plugins/tempfile.rb +1 -3
  170. data/lib/shrine/plugins/type_predicates.rb +113 -0
  171. data/lib/shrine/plugins/upload_endpoint.rb +28 -24
  172. data/lib/shrine/plugins/upload_options.rb +14 -15
  173. data/lib/shrine/plugins/url_options.rb +31 -0
  174. data/lib/shrine/plugins/validation.rb +80 -0
  175. data/lib/shrine/plugins/validation_helpers.rb +35 -58
  176. data/lib/shrine/plugins/versions.rb +107 -87
  177. data/lib/shrine/plugins.rb +22 -0
  178. data/lib/shrine/storage/file_system.rb +46 -64
  179. data/lib/shrine/storage/linter.rb +42 -7
  180. data/lib/shrine/storage/memory.rb +49 -0
  181. data/lib/shrine/storage/s3.rb +173 -160
  182. data/lib/shrine/uploaded_file.rb +32 -32
  183. data/lib/shrine/version.rb +3 -3
  184. data/lib/shrine.rb +87 -150
  185. data/shrine.gemspec +11 -12
  186. metadata +92 -82
  187. data/doc/migrating_storage.md +0 -76
  188. data/doc/plugins/backup.md +0 -31
  189. data/doc/plugins/copy.md +0 -24
  190. data/doc/plugins/delete_promoted.md +0 -12
  191. data/doc/plugins/direct_upload.md +0 -172
  192. data/doc/plugins/hooks.md +0 -58
  193. data/doc/plugins/logging.md +0 -42
  194. data/doc/plugins/migration_helpers.md +0 -60
  195. data/doc/plugins/moving.md +0 -19
  196. data/doc/plugins/multi_delete.md +0 -20
  197. data/doc/plugins/parallelize.md +0 -16
  198. data/doc/plugins/parsed_json.md +0 -23
  199. data/doc/regenerating_versions.md +0 -143
  200. data/lib/shrine/plugins/background_helpers.rb +0 -5
  201. data/lib/shrine/plugins/backup.rb +0 -90
  202. data/lib/shrine/plugins/copy.rb +0 -50
  203. data/lib/shrine/plugins/delete_promoted.rb +0 -20
  204. data/lib/shrine/plugins/direct_upload.rb +0 -217
  205. data/lib/shrine/plugins/hooks.rb +0 -90
  206. data/lib/shrine/plugins/logging.rb +0 -142
  207. data/lib/shrine/plugins/migration_helpers.rb +0 -70
  208. data/lib/shrine/plugins/moving.rb +0 -57
  209. data/lib/shrine/plugins/multi_delete.rb +0 -32
  210. data/lib/shrine/plugins/parallelize.rb +0 -78
  211. data/lib/shrine/plugins/parsed_json.rb +0 -29
@@ -1,172 +0,0 @@
1
- # Direct Upload
2
-
3
- *[OBSOLETE] This plugin is obsolete, you should use `upload_endpoint` or
4
- `presign_endpoint` plugins instead.*
5
-
6
- The [`direct_upload`][direct_upload] plugin provides a Rack endpoint which can
7
- be used for uploading individual files asynchronously. It requires the [Roda]
8
- gem.
9
-
10
- ```rb
11
- plugin :direct_upload
12
- ```
13
-
14
- The Roda endpoint provides two routes:
15
-
16
- * `POST /:storage/upload`
17
- * `GET /:storage/presign`
18
-
19
- This first route is for doing direct uploads to your app, the received file
20
- will be uploaded the underlying storage. The second route is for doing direct
21
- uploads to a 3rd-party service, it will return the URL where the file can be
22
- uploaded to, along with the necessary request parameters.
23
-
24
- This is how you can mount the endpoint in a Rails application:
25
-
26
- ```rb
27
- Rails.application.routes.draw do
28
- mount ImageUploader::UploadEndpoint => "/images"
29
- end
30
- ```
31
-
32
- Now your application will get `POST /images/cache/upload` and `GET
33
- /images/cache/presign` routes. On the client side it is recommended to use
34
- [Uppy] for uploading files to the app or directly to the 3rd-party service.
35
-
36
- ## Uploads
37
-
38
- The upload route accepts a "file" query parameter, and returns the uploaded
39
- file in JSON format:
40
-
41
- ```rb
42
- # POST /images/cache/upload
43
- {
44
- "id": "43kewit94.jpg",
45
- "storage": "cache",
46
- "metadata": {
47
- "size": 384393,
48
- "filename": "nature.jpg",
49
- "mime_type": "image/jpeg"
50
- }
51
- }
52
- ```
53
-
54
- Once you've uploaded the file, you can assign the result to the hidden
55
- attachment field in the form, or immediately send it to the server.
56
-
57
- Note that the endpoint uploads the file standalone, without any knowledge of
58
- the record, so `context[:record]` and `context[:name]` will be nil.
59
-
60
- ### Limiting filesize
61
-
62
- It's good idea to limit the maximum filesize of uploaded files, if you set the
63
- `:max_size` option, files which are too big will get automatically deleted and
64
- 413 status will be returned:
65
-
66
- ```rb
67
- plugin :direct_upload, max_size: 5*1024*1024 # 5 MB
68
- ```
69
-
70
- Note that this option doesn't affect presigned uploads, there you can apply
71
- filesize limit when generating a presign. The filesize constraint here is for
72
- security purposes, you should still perform file validations on attaching.
73
-
74
- ## Presigns
75
-
76
- The presign route returns the URL to the 3rd-party service to which you can
77
- upload the file, along with the necessary query parameters.
78
-
79
- ```rb
80
- # GET /images/cache/presign
81
- {
82
- "url" => "https://my-bucket.s3-eu-west-1.amazonaws.com",
83
- "fields" => {
84
- "key" => "b7d575850ba61b44c8a9ff889dfdb14d88cdc25f8dd121004c8",
85
- "policy" => "eyJleHBpcmF0aW9uIjoiMjAxNS0QwMToxMToyOVoiLCJjb2...",
86
- "x-amz-credential" => "AKIAIJF55TMZYT6Q/20151024/eu-west-1/s3/aws4_request",
87
- "x-amz-algorithm" => "AWS4-HMAC-SHA256",
88
- "x-amz-date" => "20151024T001129Z",
89
- "x-amz-signature" => "c1eb634f83f96b69bd675f535b3ff15ae184b102fcba51e4db5f4959b4ae26f4"
90
- }
91
- }
92
- ```
93
-
94
- If you want that the generated location includes a file extension, you can
95
- specify the `extension` query parameter: `GET
96
- /:storage/presign?extension=.png`.
97
-
98
- You can also completely change how the key is generated, with
99
- `:presign_location`:
100
-
101
- ```rb
102
- plugin :direct_upload, presign_location: -> (request) { "${filename}" }
103
- ```
104
-
105
- This presign route internally calls `#presign` on the storage, and many
106
- storages accept additional service-specific options. You can generate these
107
- additional options per-request through `:presign_options`:
108
-
109
- ```rb
110
- plugin :direct_upload, presign_options: { acl: "public-read" }
111
-
112
- plugin :direct_upload, presign_options: ->(request) do
113
- filename = request.params["filename"]
114
- content_type = Rack::Mime.mime_type(File.extname(filename))
115
-
116
- {
117
- content_length_range: 0..(10*1024*1024), # limit filesize to 10MB
118
- content_disposition: "attachment; filename=\"#{filename}\"", # download with original filename
119
- content_type: content_type, # set correct content type
120
- }
121
- end
122
- ```
123
-
124
- Both `:presign_location` and `:presign_options` in their block versions are
125
- yielded an instance of [Roda request], which is a subclass of `Rack::Request`.
126
-
127
- See the [Direct Uploads to S3] guide for further instructions on how to hook
128
- the presigned uploads to a form.
129
-
130
- ## Allowed storages
131
-
132
- By default only uploads to `:cache` are allowed, to prevent the possibility of
133
- having orphan files in your main storage. But you can allow more storages:
134
-
135
- ```rb
136
- plugin :direct_upload, allowed_storages: [:cache, :store]
137
- ```
138
-
139
- ## Customizing endpoint
140
-
141
- Since the endpoint is a [Roda] app, it is very customizable. For example, you
142
- can add a Rack middleware to change the response status and headers:
143
-
144
- ```rb
145
- class ShrineUploadMiddleware
146
- def initialize(app)
147
- @app = app
148
- end
149
-
150
- def call(env)
151
- result = @app.call(env)
152
-
153
- if result[0] == 200 && env["PATH_INFO"].end_with?("upload")
154
- result[0] = 201
155
- result[1]["Location"] = Shrine.uploaded_file(result[2].first).url
156
- end
157
-
158
- result
159
- end
160
- end
161
-
162
- Shrine::UploadEndpoint.use ShrineUploadMiddleware
163
- ```
164
-
165
- Upon subclassing uploader the upload endpoint is also subclassed. You can also
166
- call the plugin again in an uploader subclass to change its configuration.
167
-
168
- [direct_upload]: /lib/shrine/plugins/direct_upload.rb
169
- [Roda]: https://github.com/jeremyevans/roda
170
- [Uppy]: https://uppy.io
171
- [Roda request]: http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/Base/RequestMethods.html
172
- [Direct Uploads to S3]: /doc/direct_s3.md#readme
data/doc/plugins/hooks.md DELETED
@@ -1,58 +0,0 @@
1
- # Hooks
2
-
3
- The [`hooks`][hooks] plugin allows you to trigger some code around
4
- processing/storing/deleting of each file.
5
-
6
- ```rb
7
- plugin :hooks
8
- ```
9
-
10
- Shrine uses instance methods for hooks. To define a hook for an uploader, you
11
- just add an instance method to the uploader:
12
-
13
- ```rb
14
- class ImageUploader < Shrine
15
- def around_process(io, context)
16
- super
17
- rescue
18
- ExceptionNotifier.processing_failed(io, context)
19
- end
20
- end
21
- ```
22
-
23
- Each hook will be called with 2 arguments, `io` and `context`. You should
24
- always call `super` when overriding a hook, as other plugins may be using hooks
25
- internally, and without `super` those wouldn't get executed.
26
-
27
- Shrine calls hooks in the following order when uploading a file:
28
-
29
- * `before_upload`
30
- * `around_upload`
31
- - `before_process`
32
- - `around_process`
33
- - `after_process`
34
- - `before_store`
35
- - `around_store`
36
- - `after_store`
37
- * `after_upload`
38
-
39
- Shrine calls hooks in the following order when deleting a file:
40
-
41
- * `before_delete`
42
- * `around_delete`
43
- * `after_delete`
44
-
45
- By default every `around_*` hook returns the result of the corresponding
46
- operation:
47
-
48
- ```rb
49
- class ImageUploader < Shrine
50
- def around_store(io, context)
51
- result = super
52
- result.class #=> Shrine::UploadedFile
53
- result # it's good to always return the result for consistent behaviour
54
- end
55
- end
56
- ```
57
-
58
- [hooks]: /lib/shrine/plugins/hooks.rb
@@ -1,42 +0,0 @@
1
- # Logging
2
-
3
- The [`logging`][logging] plugin logs any storing/processing/deleting that is
4
- performed.
5
-
6
- ```rb
7
- plugin :logging
8
- ```
9
-
10
- This plugin is useful when you want to have overview of what exactly is going
11
- on, or you simply want to have it logged for future debugging. By default the
12
- logging output looks something like this:
13
-
14
- ```
15
- 2015-10-09T20:06:06.676Z #25602: STORE[cache] ImageUploader[:avatar] User[29543] 1 file (0.1s)
16
- 2015-10-09T20:06:06.854Z #25602: PROCESS[store]: ImageUploader[:avatar] User[29543] 1-3 files (0.22s)
17
- 2015-10-09T20:06:07.133Z #25602: DELETE[destroyed]: ImageUploader[:avatar] User[29543] 3 files (0.07s)
18
- ```
19
-
20
- The plugin accepts the following options:
21
-
22
- | Option | Description |
23
- | :-------- | :---------- |
24
- | `:format` | This allows you to change the logging output into something that may be easier to grep. Accepts `:human` (default), `:json` and `:logfmt`. |
25
- | `:stream` | The default logging stream is `$stdout`, but you may want to change it, e.g. if you log into a file. This option is passed directly to `Logger.new` (from the "logger" Ruby standard library). |
26
- | `:logger` | This allows you to change the logger entirely. This is useful for example in Rails applications, where you might want to assign this option to `Rails.logger`. |
27
-
28
- The default format is probably easiest to read, but may not be easiest to grep.
29
- If this is important to you, you can switch to another format:
30
-
31
- ```rb
32
- plugin :logging, format: :json
33
- # {"action":"upload","phase":"cache","uploader":"ImageUploader","attachment":"avatar",...}
34
-
35
- plugin :logging, format: :logfmt
36
- # action=upload phase=cache uploader=ImageUploader attachment=avatar record_class=User ...
37
- ```
38
-
39
- Logging is by default disabled in tests, but you can enable it by setting
40
- `Shrine.logger.level = Logger::INFO`.
41
-
42
- [logging]: /lib/shrine/plugins/logging.rb
@@ -1,60 +0,0 @@
1
- # Migration Helpers
2
-
3
- The [`migration_helpers`][migration_helpers] plugin gives the attacher
4
- additional helper methods which are convenient when doing file migrations.
5
-
6
- The plugin also allows convenient delegating to these methods through the
7
- model, by setting `:delegate`:
8
-
9
- ```rb
10
- plugin :migration_helpers, delegate: true
11
- ```
12
-
13
- ## `update_stored`
14
-
15
- This method updates the record's attachment with the result of the given block.
16
-
17
- ```rb
18
- user.avatar_attacher.update_stored do |avatar|
19
- user.avatar_attacher.store.upload(avatar) # saved to the record
20
- end
21
-
22
- # with model delegation
23
- user.update_avatar do |avatar|
24
- user.avatar_store.upload(avatar) # saved to the record
25
- end
26
- ```
27
-
28
- The block will get triggered _only_ if the attachment is present and not
29
- cached, *and* will save the record only if the record's attachment hasn't
30
- changed in the time it took to execute the block. This method is most useful
31
- for adding/removing versions and changing locations of files.
32
-
33
- ## `cached?` and `stored?`
34
-
35
- These methods return true if attachment exists and is cached/stored:
36
-
37
- ```rb
38
- user.avatar_attacher.cached? # user.avatar && user.avatar_attacher.cache.uploaded?(user.avatar)
39
- user.avatar_attacher.stored? # user.avatar && user.avatar_attacher.store.uploaded?(user.avatar)
40
-
41
- # with model delegation
42
- user.avatar_cached?
43
- user.avatar_stored?
44
- ```
45
-
46
- ## `attachment_cache` and `attachment_store`
47
-
48
- These methods return cache and store uploaders used by the underlying attacher:
49
-
50
- ```rb
51
- # these methods already exist without migration_helpers
52
- user.avatar_attacher.cache #=> #<Shrine @storage_key=:cache @storage=#<Shrine::Storage::FileSystem @directory=public/uploads>>
53
- user.avatar_attacher.store #=> #<Shrine @storage_key=:store @storage=#<Shrine::Storage::S3:0x007fb8343397c8 @bucket=#<Aws::S3::Bucket name="foo">>>
54
-
55
- # with model delegation
56
- user.avatar_cache
57
- user.avatar_store
58
- ```
59
-
60
- [migration_helpers]: /lib/shrine/plugins/migration_helpers.rb
@@ -1,19 +0,0 @@
1
- # Moving
2
-
3
- The [`moving`][moving] plugin will *move* files to storages instead of copying
4
- them, when the storage supports it. For FileSystem this will issue a `mv`
5
- command, which is instantaneous regardless of the filesize, so in that case
6
- loading this plugin can significantly speed up the attachment process.
7
-
8
- ```rb
9
- plugin :moving
10
- ```
11
-
12
- By default files will be moved whenever the storage supports it. If you want
13
- moving to happen only for certain storages, you can set `:storages`:
14
-
15
- ```rb
16
- plugin :moving, storages: [:cache]
17
- ```
18
-
19
- [moving]: /lib/shrine/plugins/moving.rb
@@ -1,20 +0,0 @@
1
- # Multi Delete
2
-
3
- The [`multi_delete`][multi_delete] plugins allows you to leverage your
4
- storage's multi delete capabilities.
5
-
6
- ```rb
7
- plugin :multi_delete
8
- ```
9
-
10
- This plugin allows you pass an array of files to `Shrine#delete`.
11
-
12
- ```rb
13
- uploader.delete([file1, file2, file3])
14
- ```
15
-
16
- Now if you're using Storage::S3, deleting an array of files will issue a single
17
- HTTP request. Some other storages may support multi deletes as well. The
18
- `versions` plugin uses this plugin for deleting multiple versions at once.
19
-
20
- [multi_delete]: /lib/shrine/plugins/multi_delete.rb
@@ -1,16 +0,0 @@
1
- # Parallelize
2
-
3
- The [`parallelize`][parallelize] plugin parallelizes uploads and deletes of
4
- multiple versions using threads.
5
-
6
- ```rb
7
- plugin :parallelize
8
- ```
9
-
10
- By default a pool of 3 threads will be used, but you can change that:
11
-
12
- ```rb
13
- plugin :parallelize, threads: 5
14
- ```
15
-
16
- [parallelize]: /lib/shrine/plugins/parallelize.rb
@@ -1,23 +0,0 @@
1
- # Parsed JSON
2
-
3
- The [`parsed_json`][parsed_json] plugin is suitable for the case when your
4
- framework is automatically parsing JSON query parameters, allowing you to
5
- assign cached files with hashes/arrays.
6
-
7
- ```rb
8
- plugin :parsed_json
9
- ```
10
-
11
- ```rb
12
- photo.image = {
13
- "id" => "sdf90s2443.jpg",
14
- "storage" => "cache",
15
- "metadata" => {
16
- "filename" => "nature.jpg",
17
- "size" => 29475,
18
- "mime_type" => "image/jpeg",
19
- }
20
- }
21
- ```
22
-
23
- [parsed_json]: /lib/shrine/plugins/parsed_json.rb
@@ -1,143 +0,0 @@
1
- # Reprocessing Versions
2
-
3
- While your app is serving uploads in production, you may realize that you want
4
- to change how your attachment's versions are generated. This means that, in
5
- addition to changing your processing code, you also need to reprocess the
6
- existing attachments. This guide is aimed to help doing this migration with
7
- zero downtime and no unused files left in the main storage.
8
-
9
- ## Adding versions
10
-
11
- Most common scenario is when initially you're not doing any processing, but
12
- later decide that you want to generate versions. First you need to update your
13
- code to generate versions, and you also need to change your views to use those
14
- versions:
15
-
16
- ```rb
17
- class ImageUploader < Shrine
18
- # ...
19
-
20
- process(:store) do |io, context|
21
- thumbnail = process_thumbnail(io.download)
22
- {original: io, thumbnail: thumbnail}
23
- end
24
- end
25
- ```
26
- ```rb
27
- # In your views add the version name to all <attachment>_url calls.
28
- user.avatar_url(:thumb)
29
- ```
30
-
31
- Note that you should deploy both of these changes at once, because the
32
- `<attachment>_url` method will fail if there are versions generated but no
33
- version name was passed in. If a version name was passed in but versions aren't
34
- generated yet (which will be the case here), it will just return the
35
- unprocessed file URL.
36
-
37
- Afterwards you should run a script which reprocesses the versions for existing
38
- files:
39
-
40
- ```rb
41
- User.paged_each do |user|
42
- attacher, attachment = user.avatar_attacher, user.avatar
43
- if attacher.stored? && !attachment.is_a?(Hash)
44
- file = some_processing(attachment.download)
45
- thumb = attacher.store!(file, version: :thumb)
46
- attacher.swap({original: attachment, thumb: thumb})
47
- end
48
- end
49
- ```
50
-
51
- ## Reprocessing a single version
52
-
53
- The simplest scenario is where you need to regenerate an existing version.
54
- First you need to change and deploy your updated processing code, and
55
- afterwards you can run a script like this on your production database:
56
-
57
- ```rb
58
- User.paged_each do |user|
59
- attacher, attachment = user.avatar_attacher, user.avatar
60
- if attacher.stored?
61
- file = some_processing(attachment[:original].download)
62
- thumb = attachment[:thumb].replace(thumb)
63
- attacher.swap(attachment.merge(thumb: thumb))
64
- end
65
- end
66
- ```
67
-
68
- ### Adding a new version
69
-
70
- When adding a new version to a production app, first add it to the list and
71
- update your processing code to generate it, and deploy it:
72
-
73
- ```rb
74
- class ImageUploader < Shrine
75
- # ...
76
-
77
- process(:store) do |io, context|
78
- # ...
79
- new = some_processing(io.download, *args)
80
- {small: small, medium: medium, new: new} # we generate the ":new" version
81
- end
82
- end
83
- ```
84
-
85
- After you've deployed this change, you should run a script that will generate
86
- the new version for all existing records:
87
-
88
- ```rb
89
- User.paged_each do |user|
90
- attacher, attachment = user.avatar_attacher, user.avatar
91
- if attacher.stored? && !attachment[:new]
92
- file = some_processing(attachment[:original].download, *args)
93
- new = attacher.store!(file, version: :new)
94
- attacher.swap(attachment.merge(new: new))
95
- end
96
- end
97
- ```
98
-
99
- After you've run this script on your production database, all records should
100
- have the new version, and now you should be able to safely update your app to
101
- use it.
102
-
103
- ### Removing a version
104
-
105
- Before removing a version, you first need to update your processing to not
106
- generate it (but keep the version name in the list), as well as update your app
107
- not to use the new version, and deploy that code. After you've done that, you
108
- can run a script which removes that version:
109
-
110
- ```rb
111
- old_versions = []
112
-
113
- User.paged_each do |user|
114
- attacher, attachment = user.avatar_attacher, user.avatar
115
- if attacher.stored? && attachment[:old_version]
116
- old_versions << attachment.delete(:old_version)
117
- attacher.swap(attachment)
118
- end
119
- end
120
-
121
- if old_versions.any?
122
- uploader = old_versions.first.uploader
123
- uploader.delete(old_versions)
124
- end
125
- ```
126
-
127
- After the script has finished, you should be able to safely remove the version
128
- name from the list.
129
-
130
- ## Reprocessing all versions
131
-
132
- If you made a lot of changes to versions, it might make sense to simply
133
- regenerate all versions. After you've deployed the change in processing, you
134
- can run a script which updates existing records:
135
-
136
- ```rb
137
- User.paged_each do |user|
138
- if user.avatar_attacher.stored?
139
- # assuming your largest version is named ":original"
140
- user.update(avatar: user.avatar[:original])
141
- end
142
- end
143
- ```
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The background_helpers plugin has been renamed to \"backgrounding\". Loading the plugin through \"background_helpers\" will stop working in Shrine 3.")
4
- require "shrine/plugins/backgrounding"
5
- Shrine::Plugins.register_plugin(:background_helpers, Shrine::Plugins::Backgrounding)
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Shrine.deprecation("The backup plugin has been deprecated, the new preferred way to implement mirroring is via the instrumentation plugin – see https://github.com/shrinerb/shrine/wiki/Mirroring-Uploads. The backup plugin will be removed in Shrine 3.")
4
-
5
- class Shrine
6
- module Plugins
7
- # Documentation lives in [doc/plugins/backup.md] on GitHub.
8
- #
9
- # [doc/plugins/backup.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/backup.md
10
- module Backup
11
- def self.configure(uploader, opts = {})
12
- uploader.opts[:backup_storage] = opts.fetch(:storage, uploader.opts[:backup_storage])
13
- uploader.opts[:backup_delete] = opts.fetch(:delete, uploader.opts.fetch(:backup_delete, true))
14
-
15
- raise Error, "The :storage option is required for backup plugin" if uploader.opts[:backup_storage].nil?
16
- end
17
-
18
- module AttacherMethods
19
- # Backs up the stored file after promoting.
20
- def promote(*)
21
- result = super
22
- store_backup!(result) if result
23
- result
24
- end
25
-
26
- # Deletes the backup file in addition to the stored file.
27
- def replace
28
- result = super
29
- delete_backup!(@old) if result && delete_backup?
30
- result
31
- end
32
-
33
- # Deletes the backup file in addition to the stored file.
34
- def destroy
35
- result = super
36
- delete_backup!(get) if result && delete_backup?
37
- result
38
- end
39
-
40
- # Returns a copy of the given uploaded file with storage changed to
41
- # backup storage.
42
- def backup_file(uploaded_file)
43
- uploaded_file(uploaded_file.to_json) do |file|
44
- file.data["storage"] = backup_storage.to_s
45
- end
46
- end
47
-
48
- private
49
-
50
- # Upload the stored file to the backup storage.
51
- def store_backup!(stored_file)
52
- options = _equalize_phase_and_action(action: :backup, move: false)
53
- backup_store.upload(stored_file, context.merge(options))
54
- end
55
-
56
- # Deleted the stored file from the backup storage.
57
- def delete_backup!(deleted_file)
58
- _delete(backup_file(deleted_file), action: :backup)
59
- end
60
-
61
- def backup_store
62
- @backup_store ||= shrine_class.new(backup_storage)
63
- end
64
-
65
- def backup_storage
66
- shrine_class.opts[:backup_storage]
67
- end
68
-
69
- def delete_backup?
70
- shrine_class.opts[:backup_delete]
71
- end
72
- end
73
-
74
- module InstanceMethods
75
- private
76
-
77
- # We preserve the location when uploading from store to backup.
78
- def get_location(io, context)
79
- if context[:action] == :backup
80
- io.id
81
- else
82
- super
83
- end
84
- end
85
- end
86
- end
87
-
88
- register_plugin(:backup, Backup)
89
- end
90
- end