shrine 2.15.0 → 2.16.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/doc/advantages.md +4 -0
  4. data/doc/plugins/activerecord.md +3 -2
  5. data/doc/plugins/add_metadata.md +4 -2
  6. data/doc/plugins/backgrounding.md +6 -4
  7. data/doc/plugins/backup.md +4 -2
  8. data/doc/plugins/cached_attachment_data.md +5 -3
  9. data/doc/plugins/copy.md +3 -1
  10. data/doc/plugins/data_uri.md +3 -2
  11. data/doc/plugins/default_storage.md +5 -2
  12. data/doc/plugins/default_url.md +4 -2
  13. data/doc/plugins/default_url_options.md +5 -2
  14. data/doc/plugins/delete_promoted.md +6 -4
  15. data/doc/plugins/delete_raw.md +12 -3
  16. data/doc/plugins/derivation_endpoint.md +17 -6
  17. data/doc/plugins/determine_mime_type.md +3 -2
  18. data/doc/plugins/direct_upload.md +4 -2
  19. data/doc/plugins/download_endpoint.md +46 -6
  20. data/doc/plugins/dynamic_storage.md +5 -2
  21. data/doc/plugins/hooks.md +3 -1
  22. data/doc/plugins/included.md +5 -2
  23. data/doc/plugins/infer_extension.md +5 -4
  24. data/doc/plugins/keep_files.md +5 -3
  25. data/doc/plugins/logging.md +4 -1
  26. data/doc/plugins/metadata_attribues.md +6 -3
  27. data/doc/plugins/migration_helpers.md +4 -2
  28. data/doc/plugins/module_include.md +4 -2
  29. data/doc/plugins/moving.md +6 -4
  30. data/doc/plugins/multi_delete.md +4 -2
  31. data/doc/plugins/parallelize.md +4 -2
  32. data/doc/plugins/parsed_json.md +5 -3
  33. data/doc/plugins/presign_endpoint.md +7 -5
  34. data/doc/plugins/pretty_location.md +4 -2
  35. data/doc/plugins/processing.md +3 -2
  36. data/doc/plugins/rack_file.md +4 -2
  37. data/doc/plugins/rack_response.md +26 -10
  38. data/doc/plugins/recache.md +7 -5
  39. data/doc/plugins/refresh_metadata.md +4 -2
  40. data/doc/plugins/remote_url.md +3 -1
  41. data/doc/plugins/remove_attachment.md +4 -2
  42. data/doc/plugins/remove_invalid.md +6 -3
  43. data/doc/plugins/restore_cached_data.md +8 -6
  44. data/doc/plugins/sequel.md +4 -1
  45. data/doc/plugins/signature.md +5 -3
  46. data/doc/plugins/store_dimensions.md +4 -2
  47. data/doc/plugins/tempfile.md +4 -2
  48. data/doc/plugins/upload_endpoint.md +4 -3
  49. data/doc/plugins/upload_options.md +4 -2
  50. data/doc/plugins/validation_helpers.md +4 -2
  51. data/doc/plugins/versions.md +3 -2
  52. data/doc/release_notes/2.15.0.md +2 -2
  53. data/doc/release_notes/2.16.0.md +52 -0
  54. data/doc/storage/s3.md +2 -2
  55. data/lib/shrine/plugins/_urlsafe_serialization.rb +2 -0
  56. data/lib/shrine/plugins/activerecord.rb +3 -0
  57. data/lib/shrine/plugins/add_metadata.rb +3 -0
  58. data/lib/shrine/plugins/backgrounding.rb +3 -0
  59. data/lib/shrine/plugins/backup.rb +3 -0
  60. data/lib/shrine/plugins/cached_attachment_data.rb +3 -0
  61. data/lib/shrine/plugins/copy.rb +3 -0
  62. data/lib/shrine/plugins/data_uri.rb +3 -0
  63. data/lib/shrine/plugins/default_storage.rb +3 -0
  64. data/lib/shrine/plugins/default_url.rb +3 -0
  65. data/lib/shrine/plugins/default_url_options.rb +3 -0
  66. data/lib/shrine/plugins/delete_promoted.rb +3 -0
  67. data/lib/shrine/plugins/delete_raw.rb +4 -1
  68. data/lib/shrine/plugins/derivation_endpoint.rb +144 -47
  69. data/lib/shrine/plugins/determine_mime_type.rb +3 -0
  70. data/lib/shrine/plugins/direct_upload.rb +3 -0
  71. data/lib/shrine/plugins/download_endpoint.rb +29 -29
  72. data/lib/shrine/plugins/dynamic_storage.rb +3 -0
  73. data/lib/shrine/plugins/hooks.rb +3 -0
  74. data/lib/shrine/plugins/included.rb +3 -0
  75. data/lib/shrine/plugins/infer_extension.rb +3 -0
  76. data/lib/shrine/plugins/keep_files.rb +3 -0
  77. data/lib/shrine/plugins/logging.rb +3 -0
  78. data/lib/shrine/plugins/metadata_attributes.rb +3 -0
  79. data/lib/shrine/plugins/migration_helpers.rb +3 -0
  80. data/lib/shrine/plugins/module_include.rb +3 -0
  81. data/lib/shrine/plugins/moving.rb +3 -0
  82. data/lib/shrine/plugins/multi_delete.rb +3 -0
  83. data/lib/shrine/plugins/parallelize.rb +5 -1
  84. data/lib/shrine/plugins/parsed_json.rb +3 -0
  85. data/lib/shrine/plugins/presign_endpoint.rb +3 -0
  86. data/lib/shrine/plugins/pretty_location.rb +3 -0
  87. data/lib/shrine/plugins/processing.rb +3 -0
  88. data/lib/shrine/plugins/rack_file.rb +3 -0
  89. data/lib/shrine/plugins/rack_response.rb +14 -14
  90. data/lib/shrine/plugins/recache.rb +3 -0
  91. data/lib/shrine/plugins/refresh_metadata.rb +3 -0
  92. data/lib/shrine/plugins/remote_url.rb +3 -0
  93. data/lib/shrine/plugins/remove_attachment.rb +3 -0
  94. data/lib/shrine/plugins/remove_invalid.rb +3 -0
  95. data/lib/shrine/plugins/restore_cached_data.rb +3 -0
  96. data/lib/shrine/plugins/sequel.rb +3 -0
  97. data/lib/shrine/plugins/signature.rb +3 -0
  98. data/lib/shrine/plugins/store_dimensions.rb +4 -1
  99. data/lib/shrine/plugins/tempfile.rb +5 -0
  100. data/lib/shrine/plugins/upload_endpoint.rb +3 -0
  101. data/lib/shrine/plugins/upload_options.rb +3 -0
  102. data/lib/shrine/plugins/validation_helpers.rb +3 -0
  103. data/lib/shrine/plugins/versions.rb +3 -0
  104. data/lib/shrine/uploaded_file.rb +15 -7
  105. data/lib/shrine/version.rb +1 -1
  106. metadata +3 -2
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/determine_mime_type.md] on GitHub.
6
+ #
7
+ # [doc/plugins/determine_mime_type.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/determine_mime_type.md
5
8
  module DetermineMimeType
6
9
  def self.configure(uploader, opts = {})
7
10
  if opts[:analyzer] == :default
@@ -7,6 +7,9 @@ require "json"
7
7
 
8
8
  class Shrine
9
9
  module Plugins
10
+ # Documentation lives in [doc/plugins/direct_upload.md] on GitHub.
11
+ #
12
+ # [doc/plugins/direct_upload.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/direct_upload.md
10
13
  module DirectUpload
11
14
  def self.load_dependencies(uploader, *)
12
15
  uploader.plugin :rack_file
@@ -4,36 +4,19 @@ require "roda"
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/download_endpoint.md] on GitHub.
8
+ #
9
+ # [doc/plugins/download_endpoint.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/download_endpoint.md
7
10
  module DownloadEndpoint
8
11
  def self.load_dependencies(uploader, opts = {})
9
12
  uploader.plugin :rack_response
10
13
  uploader.plugin :_urlsafe_serialization
11
14
  end
12
15
 
13
- # Accepts the following options:
14
- #
15
- # :prefix
16
- # : The location where the download endpoint was mounted. If it was
17
- # mounted at the root level, this should be set to nil.
18
- #
19
- # :host
20
- # : The host that you want the download URLs to use (e.g. your app's domain
21
- # name or a CDN). By default URLs are relative.
22
- #
23
- # :disposition
24
- # : Can be set to "attachment" if you want that the user is always
25
- # prompted to download the file when visiting the download URL.
26
- # The default is "inline".
27
- #
28
- # :redirect
29
- # : If set to `true`, requests will redirect to the direct file URL. If
30
- # set to a proc object, the proc will called with the `UploadedFile`
31
- # instance and the `Rack::Request` object, and is expected to return
32
- # the URL to which the request will redirect to. Defaults to `false`,
33
- # meaning that the file content will be served through the endpoint.
34
16
  def self.configure(uploader, opts = {})
35
17
  uploader.opts[:download_endpoint_storages] = opts.fetch(:storages, uploader.opts[:download_endpoint_storages])
36
18
  uploader.opts[:download_endpoint_prefix] = opts.fetch(:prefix, uploader.opts[:download_endpoint_prefix])
19
+ uploader.opts[:download_endpoint_download_options] = opts.fetch(:download_options, uploader.opts.fetch(:download_endpoint_download_options, {}))
37
20
  uploader.opts[:download_endpoint_disposition] = opts.fetch(:disposition, uploader.opts.fetch(:download_endpoint_disposition, "inline"))
38
21
  uploader.opts[:download_endpoint_host] = opts.fetch(:host, uploader.opts[:download_endpoint_host])
39
22
  uploader.opts[:download_endpoint_redirect] = opts.fetch(:redirect, uploader.opts.fetch(:download_endpoint_redirect, false))
@@ -68,8 +51,9 @@ class Shrine
68
51
  def new_download_endpoint(klass)
69
52
  endpoint_class = Class.new(klass)
70
53
  endpoint_class.opts[:shrine_class] = self
71
- endpoint_class.opts[:disposition] = opts[:download_endpoint_disposition]
72
- endpoint_class.opts[:redirect] = opts[:download_endpoint_redirect]
54
+ endpoint_class.opts[:download_options] = opts[:download_endpoint_download_options]
55
+ endpoint_class.opts[:disposition] = opts[:download_endpoint_disposition]
56
+ endpoint_class.opts[:redirect] = opts[:download_endpoint_redirect]
73
57
  endpoint_class
74
58
  end
75
59
  end
@@ -165,12 +149,16 @@ class Shrine
165
149
 
166
150
  # Streams the uploaded file content.
167
151
  def stream_file(uploaded_file)
168
- range = env["HTTP_RANGE"]
152
+ open_file(uploaded_file)
169
153
 
170
- status, headers, body = uploaded_file.to_rack_response(disposition: disposition, range: range)
171
- headers["Cache-Control"] = "max-age=#{365*24*60*60}" # cache for a year
154
+ response = uploaded_file.to_rack_response(
155
+ disposition: disposition,
156
+ range: env["HTTP_RANGE"],
157
+ )
172
158
 
173
- request.halt [status, headers, body]
159
+ response[1]["Cache-Control"] = "max-age=#{365*24*60*60}" # cache for a year
160
+
161
+ request.halt response
174
162
  end
175
163
 
176
164
  # Redirects to the uploaded file's direct URL or the specified URL proc.
@@ -184,6 +172,14 @@ class Shrine
184
172
  request.redirect redirect_url
185
173
  end
186
174
 
175
+ def open_file(uploaded_file)
176
+ if download_options.respond_to?(:call)
177
+ uploaded_file.open(**download_options.call(uploaded_file, request))
178
+ else
179
+ uploaded_file.open(**download_options)
180
+ end
181
+ end
182
+
187
183
  # Returns a Shrine::UploadedFile, or returns 404 if file doesn't exist.
188
184
  def get_uploaded_file(serialized)
189
185
  uploaded_file = shrine_class::UploadedFile.urlsafe_load(serialized)
@@ -205,8 +201,8 @@ class Shrine
205
201
  request.halt
206
202
  end
207
203
 
208
- def storage_names
209
- shrine_class.storages.keys.map(&:to_s)
204
+ def download_options
205
+ opts[:download_options]
210
206
  end
211
207
 
212
208
  def redirect
@@ -220,6 +216,10 @@ class Shrine
220
216
  def shrine_class
221
217
  opts[:shrine_class]
222
218
  end
219
+
220
+ def storage_names
221
+ shrine_class.storages.keys.map(&:to_s)
222
+ end
223
223
  end
224
224
  end
225
225
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/dynamic_storage.md] on GitHub.
6
+ #
7
+ # [doc/plugins/dynamic_storage.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/dynamic_storage.md
5
8
  module DynamicStorage
6
9
  def self.configure(uploader, options = {})
7
10
  uploader.opts[:dynamic_storages] ||= {}
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/hooks.md] on GitHub.
6
+ #
7
+ # [doc/plugins/hooks.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/hooks.md
5
8
  module Hooks
6
9
  module InstanceMethods
7
10
  def upload(io, context = {})
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/included.md] on GitHub.
6
+ #
7
+ # [doc/plugins/included.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/included.md
5
8
  module Included
6
9
  def self.configure(uploader, &block)
7
10
  uploader.opts[:included_block] = block
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/infer_extension.md] on GitHub.
6
+ #
7
+ # [doc/plugins/infer_extension.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/infer_extension.md
5
8
  module InferExtension
6
9
  def self.configure(uploader, opts = {})
7
10
  uploader.opts[:infer_extension_inferrer] = opts.fetch(:inferrer, uploader.opts.fetch(:infer_extension_inferrer, :mime_types))
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/keep_files.md] on GitHub.
6
+ #
7
+ # [doc/plugins/keep_files.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/keep_files.md
5
8
  module KeepFiles
6
9
  def self.configure(uploader, opts = {})
7
10
  keep_files = (uploader.opts[:keep_files] ||= [])
@@ -6,6 +6,9 @@ require "time"
6
6
 
7
7
  class Shrine
8
8
  module Plugins
9
+ # Documentation lives in [doc/plugins/logging.md] on GitHub.
10
+ #
11
+ # [doc/plugins/logging.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/logging.md
9
12
  module Logging
10
13
  def self.load_dependencies(uploader, *)
11
14
  uploader.plugin :hooks
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/metadata_attributes.md] on GitHub.
6
+ #
7
+ # [doc/plugins/metadata_attributes.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/metadata_attributes.md
5
8
  module MetadataAttributes
6
9
  def self.configure(uploader, mappings = {})
7
10
  uploader.opts[:metadata_attributes_mappings] ||= {}
@@ -4,6 +4,9 @@ Shrine.deprecation("The migration_helpers plugin is deprecated and will be remov
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/migration_helpers.md] on GitHub.
8
+ #
9
+ # [doc/plugins/migration_helpers.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/migration_helpers.md
7
10
  module MigrationHelpers
8
11
  def self.configure(uploader, delegate: false)
9
12
  uploader.opts[:migration_helpers_delegate] = delegate
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/module_include.md] on GitHub.
6
+ #
7
+ # [doc/plugins/module_include.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/module_include.md
5
8
  module ModuleInclude
6
9
  module ClassMethods
7
10
  def attachment_module(mod = nil, &block)
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/moving.md] on GitHub.
6
+ #
7
+ # [doc/plugins/moving.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/moving.md
5
8
  module Moving
6
9
  def self.configure(uploader, opts = {})
7
10
  uploader.opts[:moving_storages] = opts.fetch(:storages, uploader.opts[:moving_storages])
@@ -4,6 +4,9 @@ Shrine.deprecation("The multi_delete plugin is deprecated and will be removed in
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/multi_delete.md] on GitHub.
8
+ #
9
+ # [doc/plugins/multi_delete.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/multi_delete.md
7
10
  module MultiDelete
8
11
  module InstanceMethods
9
12
  private
@@ -4,6 +4,9 @@ require "thread"
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/parallelize.md] on GitHub.
8
+ #
9
+ # [doc/plugins/parallelize.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/parallelize.md
7
10
  module Parallelize
8
11
  def self.configure(uploader, opts = {})
9
12
  uploader.opts[:parallelize_threads] = opts.fetch(:threads, uploader.opts.fetch(:parallelize_threads, 3))
@@ -52,6 +55,7 @@ class Shrine
52
55
  end
53
56
 
54
57
  def perform
58
+ @tasks.close
55
59
  threads = @size.times.map { spawn_thread }
56
60
  threads.each(&:join)
57
61
  end
@@ -61,7 +65,7 @@ class Shrine
61
65
  def spawn_thread
62
66
  Thread.new do
63
67
  loop do
64
- task = @tasks.deq(true) rescue break
68
+ task = @tasks.deq or break
65
69
  task.call
66
70
  end
67
71
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/parsed_json.md] on GitHub.
6
+ #
7
+ # [doc/plugins/parsed_json.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/parsed_json.md
5
8
  module ParsedJson
6
9
  module AttacherMethods
7
10
  def assign(value)
@@ -6,6 +6,9 @@ require "json"
6
6
 
7
7
  class Shrine
8
8
  module Plugins
9
+ # Documentation lives in [doc/plugins/presign_endpoint.md] on GitHub.
10
+ #
11
+ # [doc/plugins/presign_endpoint.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/presign_endpoint.md
9
12
  module PresignEndpoint
10
13
  def self.configure(uploader, opts = {})
11
14
  uploader.opts[:presign_endpoint_presign_location] = opts.fetch(:presign_location, uploader.opts[:presign_endpoint_presign_location])
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/pretty_location.md] on GitHub.
6
+ #
7
+ # [doc/plugins/pretty_location.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/pretty_location.md
5
8
  module PrettyLocation
6
9
  def self.configure(uploader, opts = {})
7
10
  uploader.opts[:pretty_location_namespace] = opts.fetch(:namespace, uploader.opts[:pretty_location_namespace])
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/processing.md] on GitHub.
6
+ #
7
+ # [doc/plugins/processing.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/processing.md
5
8
  module Processing
6
9
  def self.configure(uploader)
7
10
  uploader.opts[:processing] ||= {}
@@ -4,6 +4,9 @@ require "forwardable"
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/rack_file.md] on GitHub.
8
+ #
9
+ # [doc/plugins/rack_file.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/rack_file.md
7
10
  module RackFile
8
11
  module ClassMethods
9
12
  # Accepts a Rack uploaded file hash and wraps it in an IO object.
@@ -5,6 +5,9 @@ require "content_disposition"
5
5
 
6
6
  class Shrine
7
7
  module Plugins
8
+ # Documentation lives in [doc/plugins/rack_response.md] on GitHub.
9
+ #
10
+ # [doc/plugins/rack_response.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/rack_response.md
8
11
  module RackResponse
9
12
  module FileMethods
10
13
  # Returns a Rack response triple for the uploaded file.
@@ -22,6 +25,8 @@ class Shrine
22
25
 
23
26
  # Returns a Rack response triple for the uploaded file.
24
27
  def call(**options)
28
+ file.open unless file.opened?
29
+
25
30
  options[:range] = parse_content_range(options[:range]) if options[:range]
26
31
 
27
32
  status = rack_status(**options)
@@ -44,15 +49,15 @@ class Shrine
44
49
  # metadata. Also returns the correct "Content-Range" header on ranged
45
50
  # requests.
46
51
  def rack_headers(filename: nil, type: nil, disposition: "inline", range: false)
47
- length = range ? range.size : size
48
- type ||= @file.mime_type || Rack::Mime.mime_type(".#{@file.extension}")
49
- filename ||= @file.original_filename || @file.id.split("/").last
52
+ length = range ? range.size : file.size
53
+ type ||= file.mime_type || Rack::Mime.mime_type(".#{file.extension}", nil)
54
+ filename ||= file.original_filename || file.id.split("/").last
50
55
 
51
56
  headers = {}
52
57
  headers["Content-Length"] = length.to_s if length
53
- headers["Content-Type"] = type
54
- headers["Content-Disposition"] = content_disposition(disposition: disposition, filename: filename)
55
- headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{size}" if range
58
+ headers["Content-Type"] = type if type
59
+ headers["Content-Disposition"] = content_disposition(disposition, filename)
60
+ headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{file.size}" if range
56
61
  headers["Accept-Ranges"] = "bytes" unless range == false
57
62
 
58
63
  headers
@@ -67,22 +72,17 @@ class Shrine
67
72
  # Parses the value of a "Range" HTTP header.
68
73
  def parse_content_range(range_header)
69
74
  if Rack.release >= "2.0"
70
- ranges = Rack::Utils.get_byte_ranges(range_header, size)
75
+ ranges = Rack::Utils.get_byte_ranges(range_header, file.size)
71
76
  else
72
- ranges = Rack::Utils.byte_ranges({"HTTP_RANGE" => range_header}, size)
77
+ ranges = Rack::Utils.byte_ranges({ "HTTP_RANGE" => range_header }, file.size)
73
78
  end
74
79
 
75
80
  ranges.first if ranges && ranges.one?
76
81
  end
77
82
 
78
- def content_disposition(disposition:, filename:)
83
+ def content_disposition(disposition, filename)
79
84
  ContentDisposition.format(disposition: disposition, filename: filename)
80
85
  end
81
-
82
- # Read size from metadata, otherwise retrieve the size from the storage.
83
- def size
84
- @file.size || @file.to_io.size
85
- end
86
86
  end
87
87
 
88
88
  # Implements the interface of a Rack response body object.
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/recache.md] on GitHub.
6
+ #
7
+ # [doc/plugins/recache.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/recache.md
5
8
  module Recache
6
9
  module AttacherMethods
7
10
  def save
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/refresh_metadata.md] on GitHub.
6
+ #
7
+ # [doc/plugins/refresh_metadata.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/refresh_metadata.md
5
8
  module RefreshMetadata
6
9
  module FileMethods
7
10
  def refresh_metadata!(context = {})
@@ -4,6 +4,9 @@ require "down"
4
4
 
5
5
  class Shrine
6
6
  module Plugins
7
+ # Documentation lives in [doc/plugins/remote_url.md] on GitHub.
8
+ #
9
+ # [doc/plugins/remote_url.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/remote_url.md
7
10
  module RemoteUrl
8
11
  def self.configure(uploader, opts = {})
9
12
  raise Error, "The :max_size option is required for remote_url plugin" if !opts.key?(:max_size) && !uploader.opts.key?(:remote_url_max_size)
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Shrine
4
4
  module Plugins
5
+ # Documentation lives in [doc/plugins/remove_attachment.md] on GitHub.
6
+ #
7
+ # [doc/plugins/remove_attachment.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/remove_attachment.md
5
8
  module RemoveAttachment
6
9
  module AttachmentMethods
7
10
  def initialize(*)