shrine 2.14.0 → 2.15.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +384 -374
  3. data/README.md +132 -63
  4. data/doc/advantages.md +191 -109
  5. data/doc/attacher.md +1 -1
  6. data/doc/carrierwave.md +4 -4
  7. data/doc/creating_storages.md +2 -2
  8. data/doc/design.md +2 -2
  9. data/doc/direct_s3.md +3 -3
  10. data/doc/metadata.md +1 -1
  11. data/doc/multiple_files.md +2 -2
  12. data/doc/paperclip.md +3 -3
  13. data/doc/plugins/activerecord.md +92 -0
  14. data/doc/plugins/add_metadata.md +93 -0
  15. data/doc/plugins/backgrounding.md +148 -0
  16. data/doc/plugins/backup.md +29 -0
  17. data/doc/plugins/cached_attachment_data.md +23 -0
  18. data/doc/plugins/copy.md +22 -0
  19. data/doc/plugins/data_uri.md +92 -0
  20. data/doc/plugins/default_storage.md +16 -0
  21. data/doc/plugins/default_url.md +33 -0
  22. data/doc/plugins/default_url_options.md +22 -0
  23. data/doc/plugins/delete_promoted.md +10 -0
  24. data/doc/plugins/delete_raw.md +16 -0
  25. data/doc/plugins/derivation_endpoint.md +747 -0
  26. data/doc/plugins/determine_mime_type.md +64 -0
  27. data/doc/plugins/direct_upload.md +170 -0
  28. data/doc/plugins/download_endpoint.md +83 -0
  29. data/doc/plugins/dynamic_storage.md +20 -0
  30. data/doc/plugins/hooks.md +56 -0
  31. data/doc/plugins/included.md +15 -0
  32. data/doc/plugins/infer_extension.md +57 -0
  33. data/doc/plugins/keep_files.md +20 -0
  34. data/doc/plugins/logging.md +39 -0
  35. data/doc/plugins/metadata_attribues.md +43 -0
  36. data/doc/plugins/migration_helpers.md +58 -0
  37. data/doc/plugins/module_include.md +40 -0
  38. data/doc/plugins/moving.md +17 -0
  39. data/doc/plugins/multi_delete.md +18 -0
  40. data/doc/plugins/parallelize.md +14 -0
  41. data/doc/plugins/parsed_json.md +9 -0
  42. data/doc/plugins/presign_endpoint.md +133 -0
  43. data/doc/plugins/pretty_location.md +29 -0
  44. data/doc/plugins/processing.md +68 -0
  45. data/doc/plugins/rack_file.md +49 -0
  46. data/doc/plugins/rack_response.md +96 -0
  47. data/doc/plugins/recache.md +27 -0
  48. data/doc/plugins/refresh_metadata.md +31 -0
  49. data/doc/plugins/remote_url.md +104 -0
  50. data/doc/plugins/remove_attachment.md +16 -0
  51. data/doc/plugins/remove_invalid.md +9 -0
  52. data/doc/plugins/restore_cached_data.md +14 -0
  53. data/doc/plugins/sequel.md +64 -0
  54. data/doc/plugins/signature.md +49 -0
  55. data/doc/plugins/store_dimensions.md +68 -0
  56. data/doc/plugins/tempfile.md +40 -0
  57. data/doc/plugins/upload_endpoint.md +123 -0
  58. data/doc/plugins/upload_options.md +28 -0
  59. data/doc/plugins/validation_helpers.md +129 -0
  60. data/doc/plugins/versions.md +179 -0
  61. data/doc/processing.md +217 -247
  62. data/doc/refile.md +3 -3
  63. data/doc/release_notes/1.0.0.md +143 -0
  64. data/doc/release_notes/1.1.0.md +184 -0
  65. data/doc/release_notes/1.2.0.md +37 -0
  66. data/doc/release_notes/1.3.0.md +90 -0
  67. data/doc/release_notes/1.4.0.md +167 -0
  68. data/doc/release_notes/1.4.1.md +9 -0
  69. data/doc/release_notes/1.4.2.md +20 -0
  70. data/doc/release_notes/2.0.0.md +173 -0
  71. data/doc/release_notes/2.0.1.md +12 -0
  72. data/doc/release_notes/2.1.0.md +59 -0
  73. data/doc/release_notes/2.1.1.md +8 -0
  74. data/doc/release_notes/2.10.0.md +52 -0
  75. data/doc/release_notes/2.10.1.md +6 -0
  76. data/doc/release_notes/2.11.0.md +69 -0
  77. data/doc/release_notes/2.12.0.md +65 -0
  78. data/doc/release_notes/2.13.0.md +146 -0
  79. data/doc/release_notes/2.14.0.md +278 -0
  80. data/doc/release_notes/2.15.0.md +82 -0
  81. data/doc/release_notes/2.2.0.md +98 -0
  82. data/doc/release_notes/2.3.0.md +50 -0
  83. data/doc/release_notes/2.3.1.md +10 -0
  84. data/doc/release_notes/2.4.0.md +87 -0
  85. data/doc/release_notes/2.4.1.md +29 -0
  86. data/doc/release_notes/2.5.0.md +130 -0
  87. data/doc/release_notes/2.6.0.md +254 -0
  88. data/doc/release_notes/2.6.1.md +14 -0
  89. data/doc/release_notes/2.7.0.md +180 -0
  90. data/doc/release_notes/2.8.0.md +95 -0
  91. data/doc/release_notes/2.9.0.md +82 -0
  92. data/doc/retrieving_uploads.md +1 -1
  93. data/doc/storage/file_system.md +96 -0
  94. data/doc/storage/s3.md +293 -0
  95. data/doc/validation.md +1 -1
  96. data/lib/shrine/plugins/_urlsafe_serialization.rb +33 -125
  97. data/lib/shrine/plugins/activerecord.rb +0 -78
  98. data/lib/shrine/plugins/add_metadata.rb +0 -80
  99. data/lib/shrine/plugins/backgrounding.rb +0 -134
  100. data/lib/shrine/plugins/backup.rb +0 -22
  101. data/lib/shrine/plugins/cached_attachment_data.rb +0 -15
  102. data/lib/shrine/plugins/copy.rb +0 -14
  103. data/lib/shrine/plugins/data_uri.rb +0 -73
  104. data/lib/shrine/plugins/default_storage.rb +0 -11
  105. data/lib/shrine/plugins/default_url.rb +0 -25
  106. data/lib/shrine/plugins/default_url_options.rb +0 -16
  107. data/lib/shrine/plugins/delete_promoted.rb +0 -6
  108. data/lib/shrine/plugins/delete_raw.rb +0 -10
  109. data/lib/shrine/plugins/derivation_endpoint.rb +652 -0
  110. data/lib/shrine/plugins/determine_mime_type.rb +1 -85
  111. data/lib/shrine/plugins/direct_upload.rb +0 -155
  112. data/lib/shrine/plugins/download_endpoint.rb +11 -73
  113. data/lib/shrine/plugins/dynamic_storage.rb +0 -17
  114. data/lib/shrine/plugins/hooks.rb +0 -48
  115. data/lib/shrine/plugins/included.rb +0 -12
  116. data/lib/shrine/plugins/infer_extension.rb +0 -49
  117. data/lib/shrine/plugins/keep_files.rb +0 -19
  118. data/lib/shrine/plugins/logging.rb +0 -39
  119. data/lib/shrine/plugins/metadata_attributes.rb +0 -35
  120. data/lib/shrine/plugins/migration_helpers.rb +0 -50
  121. data/lib/shrine/plugins/module_include.rb +0 -32
  122. data/lib/shrine/plugins/moving.rb +0 -12
  123. data/lib/shrine/plugins/multi_delete.rb +0 -13
  124. data/lib/shrine/plugins/parallelize.rb +0 -8
  125. data/lib/shrine/plugins/parsed_json.rb +0 -5
  126. data/lib/shrine/plugins/presign_endpoint.rb +2 -117
  127. data/lib/shrine/plugins/pretty_location.rb +0 -22
  128. data/lib/shrine/plugins/processing.rb +0 -55
  129. data/lib/shrine/plugins/rack_file.rb +0 -39
  130. data/lib/shrine/plugins/rack_response.rb +0 -81
  131. data/lib/shrine/plugins/recache.rb +0 -21
  132. data/lib/shrine/plugins/refresh_metadata.rb +0 -24
  133. data/lib/shrine/plugins/remote_url.rb +0 -85
  134. data/lib/shrine/plugins/remove_attachment.rb +0 -10
  135. data/lib/shrine/plugins/remove_invalid.rb +0 -6
  136. data/lib/shrine/plugins/restore_cached_data.rb +0 -10
  137. data/lib/shrine/plugins/sequel.rb +0 -54
  138. data/lib/shrine/plugins/signature.rb +0 -37
  139. data/lib/shrine/plugins/store_dimensions.rb +0 -63
  140. data/lib/shrine/plugins/tempfile.rb +4 -35
  141. data/lib/shrine/plugins/upload_endpoint.rb +2 -109
  142. data/lib/shrine/plugins/upload_options.rb +0 -20
  143. data/lib/shrine/plugins/validation_helpers.rb +0 -36
  144. data/lib/shrine/plugins/versions.rb +0 -156
  145. data/lib/shrine/storage/file_system.rb +0 -77
  146. data/lib/shrine/storage/s3.rb +0 -249
  147. data/lib/shrine/version.rb +1 -1
  148. data/shrine.gemspec +2 -2
  149. metadata +86 -6
@@ -0,0 +1,64 @@
1
+ # Determine MIME Type
2
+
3
+ The `determine_mime_type` plugin allows you to determine and store the actual
4
+ MIME type of the file analyzed from file content.
5
+
6
+ ```rb
7
+ plugin :determine_mime_type
8
+ ```
9
+
10
+ By default the UNIX [file] utility is used to determine the MIME type, and the
11
+ result is automatically written to the `mime_type` metadata field. You can
12
+ choose a different built-in MIME type analyzer:
13
+
14
+ ```rb
15
+ plugin :determine_mime_type, analyzer: :marcel
16
+ ```
17
+
18
+ The following analyzers are accepted:
19
+
20
+ | Name | Description |
21
+ | :------ | :----------- |
22
+ | `:file` | (Default). Uses the [file] utility to determine the MIME type from file contents. It is installed by default on most operating systems, but the [Windows equivalent] needs to be installed separately. |
23
+ | `:fastimage` | Uses the [fastimage] gem to determine the MIME type from file contents. Fastimage is optimized for speed over accuracy. Best used for image content. |
24
+ | `:filemagic` | Uses the [ruby-filemagic] gem to determine the MIME type from file contents, using a similar MIME database as the `file` utility. Unlike the `file` utility, ruby-filemagic works on Windows without any setup. |
25
+ | `:mimemagic` | Uses the [mimemagic] gem to determine the MIME type from file contents. Unlike ruby-filemagic, mimemagic is a pure-ruby solution, so it will work across all Ruby implementations. |
26
+ | `:marcel` | Uses the [marcel] gem to determine the MIME type from file contents. Marcel is Basecamp's wrapper around mimemagic, it adds priority logic (preferring magic over name when given both), some extra type definitions, and common type subclasses (including Keynote, Pages, etc). |
27
+ | `:mime_types` | Uses the [mime-types] gem to determine the MIME type from the file extension. Note that unlike other solutions, this analyzer is not guaranteed to return the actual MIME type of the file. |
28
+ | `:mini_mime` | Uses the [mini_mime] gem to determine the MIME type from the file extension. Note that unlike other solutions, this analyzer is not guaranteed to return the actual MIME type of the file. |
29
+ | `:content_type` | Retrieves the value of the `#content_type` attribute of the IO object. Note that this value normally comes from the "Content-Type" request header, so it's not guaranteed to hold the actual MIME type of the file. |
30
+
31
+ A single analyzer is not going to properly recognize all types of files, so you
32
+ can build your own custom analyzer for your requirements, where you can combine
33
+ the built-in analyzers. For example, if you want to correctly determine MIME
34
+ type of .css, .js, .json, .csv, .xml, or similar text-based files, you can
35
+ combine `file` and `mime_types` analyzers:
36
+
37
+ ```rb
38
+ plugin :determine_mime_type, analyzer: -> (io, analyzers) do
39
+ mime_type = analyzers[:file].call(io)
40
+ mime_type = analyzers[:mime_types].call(io) if mime_type == "text/plain"
41
+ mime_type
42
+ end
43
+ ```
44
+
45
+ You can also use methods for determining the MIME type directly:
46
+
47
+ ```rb
48
+ # or YourUploader.determine_mime_type(io)
49
+ Shrine.determine_mime_type(io) # calls the defined analyzer
50
+ #=> "image/jpeg"
51
+
52
+ # or YourUploader.mime_type_analyzers
53
+ Shrine.mime_type_analyzers[:file].call(io) # calls a built-in analyzer
54
+ #=> "image/jpeg"
55
+ ```
56
+
57
+ [file]: http://linux.die.net/man/1/file
58
+ [Windows equivalent]: http://gnuwin32.sourceforge.net/packages/file.htm
59
+ [ruby-filemagic]: https://github.com/blackwinter/ruby-filemagic
60
+ [mimemagic]: https://github.com/minad/mimemagic
61
+ [marcel]: https://github.com/basecamp/marcel
62
+ [mime-types]: https://github.com/mime-types/ruby-mime-types
63
+ [mini_mime]: https://github.com/discourse/mini_mime
64
+ [fastimage]: https://github.com/sdsykes/fastimage
@@ -0,0 +1,170 @@
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` plugin provides a Rack endpoint which can be used for
7
+ uploading individual files asynchronously. It requires the [Roda] gem.
8
+
9
+ ```rb
10
+ plugin :direct_upload
11
+ ```
12
+
13
+ The Roda endpoint provides two routes:
14
+
15
+ * `POST /:storage/upload`
16
+ * `GET /:storage/presign`
17
+
18
+ This first route is for doing direct uploads to your app, the received file
19
+ will be uploaded the underlying storage. The second route is for doing direct
20
+ uploads to a 3rd-party service, it will return the URL where the file can be
21
+ uploaded to, along with the necessary request parameters.
22
+
23
+ This is how you can mount the endpoint in a Rails application:
24
+
25
+ ```rb
26
+ Rails.application.routes.draw do
27
+ mount ImageUploader::UploadEndpoint => "/images"
28
+ end
29
+ ```
30
+
31
+ Now your application will get `POST /images/cache/upload` and `GET
32
+ /images/cache/presign` routes. On the client side it is recommended to use
33
+ [Uppy] for uploading files to the app or directly to the 3rd-party service.
34
+
35
+ ## Uploads
36
+
37
+ The upload route accepts a "file" query parameter, and returns the uploaded
38
+ file in JSON format:
39
+
40
+ ```rb
41
+ # POST /images/cache/upload
42
+ {
43
+ "id": "43kewit94.jpg",
44
+ "storage": "cache",
45
+ "metadata": {
46
+ "size": 384393,
47
+ "filename": "nature.jpg",
48
+ "mime_type": "image/jpeg"
49
+ }
50
+ }
51
+ ```
52
+
53
+ Once you've uploaded the file, you can assign the result to the hidden
54
+ attachment field in the form, or immediately send it to the server.
55
+
56
+ Note that the endpoint uploads the file standalone, without any knowledge of
57
+ the record, so `context[:record]` and `context[:name]` will be nil.
58
+
59
+ ### Limiting filesize
60
+
61
+ It's good idea to limit the maximum filesize of uploaded files, if you set the
62
+ `:max_size` option, files which are too big will get automatically deleted and
63
+ 413 status will be returned:
64
+
65
+ ```rb
66
+ plugin :direct_upload, max_size: 5*1024*1024 # 5 MB
67
+ ```
68
+
69
+ Note that this option doesn't affect presigned uploads, there you can apply
70
+ filesize limit when generating a presign. The filesize constraint here is for
71
+ security purposes, you should still perform file validations on attaching.
72
+
73
+ ## Presigns
74
+
75
+ The presign route returns the URL to the 3rd-party service to which you can
76
+ upload the file, along with the necessary query parameters.
77
+
78
+ ```rb
79
+ # GET /images/cache/presign
80
+ {
81
+ "url" => "https://my-bucket.s3-eu-west-1.amazonaws.com",
82
+ "fields" => {
83
+ "key" => "b7d575850ba61b44c8a9ff889dfdb14d88cdc25f8dd121004c8",
84
+ "policy" => "eyJleHBpcmF0aW9uIjoiMjAxNS0QwMToxMToyOVoiLCJjb2...",
85
+ "x-amz-credential" => "AKIAIJF55TMZYT6Q/20151024/eu-west-1/s3/aws4_request",
86
+ "x-amz-algorithm" => "AWS4-HMAC-SHA256",
87
+ "x-amz-date" => "20151024T001129Z",
88
+ "x-amz-signature" => "c1eb634f83f96b69bd675f535b3ff15ae184b102fcba51e4db5f4959b4ae26f4"
89
+ }
90
+ }
91
+ ```
92
+
93
+ If you want that the generated location includes a file extension, you can
94
+ specify the `extension` query parameter: `GET
95
+ /:storage/presign?extension=.png`.
96
+
97
+ You can also completely change how the key is generated, with
98
+ `:presign_location`:
99
+
100
+ ```rb
101
+ plugin :direct_upload, presign_location: -> (request) { "${filename}" }
102
+ ```
103
+
104
+ This presign route internally calls `#presign` on the storage, and many
105
+ storages accept additional service-specific options. You can generate these
106
+ additional options per-request through `:presign_options`:
107
+
108
+ ```rb
109
+ plugin :direct_upload, presign_options: { acl: "public-read" }
110
+
111
+ plugin :direct_upload, presign_options: ->(request) do
112
+ filename = request.params["filename"]
113
+ content_type = Rack::Mime.mime_type(File.extname(filename))
114
+
115
+ {
116
+ content_length_range: 0..(10*1024*1024), # limit filesize to 10MB
117
+ content_disposition: "attachment; filename=\"#{filename}\"", # download with original filename
118
+ content_type: content_type, # set correct content type
119
+ }
120
+ end
121
+ ```
122
+
123
+ Both `:presign_location` and `:presign_options` in their block versions are
124
+ yielded an instance of [Roda request], which is a subclass of `Rack::Request`.
125
+
126
+ See the [Direct Uploads to S3] guide for further instructions on how to hook
127
+ the presigned uploads to a form.
128
+
129
+ ## Allowed storages
130
+
131
+ By default only uploads to `:cache` are allowed, to prevent the possibility of
132
+ having orphan files in your main storage. But you can allow more storages:
133
+
134
+ ```rb
135
+ plugin :direct_upload, allowed_storages: [:cache, :store]
136
+ ```
137
+
138
+ ## Customizing endpoint
139
+
140
+ Since the endpoint is a [Roda] app, it is very customizable. For example, you
141
+ can add a Rack middleware to change the response status and headers:
142
+
143
+ ```rb
144
+ class ShrineUploadMiddleware
145
+ def initialize(app)
146
+ @app = app
147
+ end
148
+
149
+ def call(env)
150
+ result = @app.call(env)
151
+
152
+ if result[0] == 200 && env["PATH_INFO"].end_with?("upload")
153
+ result[0] = 201
154
+ result[1]["Location"] = Shrine.uploaded_file(result[2].first).url
155
+ end
156
+
157
+ result
158
+ end
159
+ end
160
+
161
+ Shrine::UploadEndpoint.use ShrineUploadMiddleware
162
+ ```
163
+
164
+ Upon subclassing uploader the upload endpoint is also subclassed. You can also
165
+ call the plugin again in an uploader subclass to change its configuration.
166
+
167
+ [Roda]: https://github.com/jeremyevans/roda
168
+ [Uppy]: https://uppy.io
169
+ [Roda request]: http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/Base/RequestMethods.html
170
+ [Direct Uploads to S3]: /doc/direct_s3.md#readme
@@ -0,0 +1,83 @@
1
+ # Download Endpoint
2
+
3
+ The `download_endpoint` plugin provides a Rack app for downloading uploaded
4
+ files from specified storages. This can be useful when files from your storage
5
+ isn't accessible over URL (e.g. database storages) or if you want to
6
+ authenticate your downloads. It requires the [Roda] gem.
7
+
8
+ ```rb
9
+ # Gemfile
10
+ gem "roda" # dependency of the download_endpoint plugin
11
+ ```
12
+
13
+ You can configure the plugin with the path prefix which the endpoint will be
14
+ mounted on.
15
+
16
+ ```rb
17
+ plugin :download_endpoint, prefix: "attachments"
18
+ ```
19
+
20
+ The endpoint should then be mounted on the specified prefix:
21
+
22
+ ```rb
23
+ # config.ru (Rack)
24
+ map "/attachments" do
25
+ run Shrine.download_endpoint
26
+ end
27
+
28
+ # OR
29
+
30
+ # config/routes.rb (Rails)
31
+ Rails.application.routes.draw do
32
+ mount Shrine.download_endpoint => "/attachments"
33
+ end
34
+ ```
35
+
36
+ Any uploaded file can be downloaded through this endpoint. When a file is
37
+ requested, its content will be efficiently streamed from the storage into the
38
+ response body.
39
+
40
+ Links to the download endpoint are generated by calling
41
+ `UploadedFile#download_url` instead of the usual `UploadedFile#url`.
42
+
43
+ ```rb
44
+ uploaded_file.download_url #=> "/attachments/eyJpZCI6ImFkdzlyeTM..."
45
+ ```
46
+
47
+ ## Host
48
+
49
+ You can specify download URL host via the `:host` plugin option:
50
+
51
+ ```rb
52
+ plugin :download_endpoint, host: "http://example.com"
53
+ ```
54
+
55
+ or by passing `:host` to `UploadedFile#download_url`:
56
+
57
+ ```rb
58
+ uploaded_file.download_url(host: "http://example.com")
59
+ #=> "http//example.com/attachments/eyJpZCI6ImFkdzlyeTM..."
60
+ ```
61
+
62
+ ## Performance considerations
63
+
64
+ Streaming files through the app might impact the request throughput, depending
65
+ on the web server you're using. So it's recommended to use a CDN, which can be
66
+ set via the `:host` option.
67
+
68
+ Alternatively, you can have the endpoint redirect to the direct file URL:
69
+
70
+ ```rb
71
+ plugin :download_endpoint, redirect: true
72
+ # or
73
+ plugin :download_endpoint, redirect: -> (uploaded_file, request) do
74
+ # return URL which the request will redirect to
75
+ end
76
+ ```
77
+
78
+ ## Custom endpoint
79
+
80
+ If you want to have more control on download requests, you can use the
81
+ `rack_response` plugin which this plugin uses internally.
82
+
83
+ [Roda]: https://github.com/jeremyevans/roda
@@ -0,0 +1,20 @@
1
+ # Dynamic Storage
2
+
3
+ The `dynamic_storage` plugin allows you to register a storage using a regex,
4
+ and evaluate the storage class dynamically depending on the regex.
5
+
6
+ Example:
7
+
8
+ ```rb
9
+ plugin :dynamic_storage
10
+
11
+ storage /store_(\w+)/ do |match|
12
+ Shrine::Storages::S3.new(bucket: match[1])
13
+ end
14
+ ```
15
+
16
+ The above example uses S3 storage where the bucket name depends on the storage
17
+ name suffix. For example, `:store_foo` will use S3 storage which saves files to
18
+ the bucket "foo". The block is yielded an instance of `MatchData`.
19
+
20
+ This can be useful in combination with the `default_storage` plugin.
@@ -0,0 +1,56 @@
1
+ # Hooks
2
+
3
+ The `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
+ ```
@@ -0,0 +1,15 @@
1
+ # Included
2
+
3
+ The `included` plugin allows you to hook up to the `.included` hook of the
4
+ attachment module, and call additional methods on the model which includes it.
5
+
6
+ ```rb
7
+ plugin :included do |name|
8
+ before_save do
9
+ # ...
10
+ end
11
+ end
12
+ ```
13
+
14
+ If you want to define additional methods on the model, it's recommended to use
15
+ the `module_include` plugin instead.
@@ -0,0 +1,57 @@
1
+ # Infer Extension
2
+
3
+ The `infer_extension` plugin allows deducing the appropriate file extension for
4
+ the upload location based on the MIME type of the file. This is useful when
5
+ using `data_uri` and `remote_url` plugins, where the file extension might not
6
+ be known.
7
+
8
+ ```rb
9
+ plugin :infer_extension
10
+ ```
11
+
12
+ Ordinarily, the upload location will gain the inferred extension only if it
13
+ couldn't be determined from the filename. However, you can pass `force: true`
14
+ to force the inferred extension to be used rather than an extension from the
15
+ original filename. This can be used to canonicalize extensions (jpg, jpeg =>
16
+ jpeg), or replace an incorrect original extension.
17
+
18
+ ```rb
19
+ plugin :infer_extension, force: true
20
+ ```
21
+
22
+ By default `MIME::Types` will be used for inferring the extension, but you can
23
+ also choose a different inferrer:
24
+
25
+ ```rb
26
+ plugin :infer_extension, inferrer: :mini_mime
27
+ ```
28
+
29
+ The following inferrers are accepted:
30
+
31
+ | Name | Description |
32
+ | :------------ | :----------- |
33
+ | `:mime_types` | (Default). Uses the [mime-types] gem to infer the appropriate extension from MIME type. |
34
+ | `:mini_mime` | Uses the [mini_mime] gem to infer the appropriate extension from MIME type. |
35
+
36
+ You can also define your own inferrer, with the possibility to call the
37
+ built-in inferrers:
38
+
39
+ ```rb
40
+ plugin :infer_extension, inferrer: -> (mime_type, inferrers) do
41
+ # don't add extension if the file is a text file
42
+ inferrers[:rack_mime].call(mime_type) unless mime_type == "text/plain"
43
+ end
44
+ ```
45
+
46
+ You can also use methods for inferring extension directly:
47
+
48
+ ```rb
49
+ Shrine.infer_extension("image/jpeg")
50
+ # => ".jpeg"
51
+
52
+ Shrine.extension_inferrers[:mime_types].call("image/jpeg")
53
+ # => ".jpeg"
54
+ ```
55
+
56
+ [mime-types]: https://github.com/mime-types/ruby-mime-types
57
+ [mini_mime]: https://github.com/discourse/mini_mime