shrine 3.0.1 → 3.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/LICENSE.txt +1 -1
- data/README.md +15 -5
- data/doc/advantages.md +33 -16
- data/doc/attacher.md +2 -2
- data/doc/carrierwave.md +78 -34
- data/doc/changing_derivatives.md +39 -39
- data/doc/design.md +134 -85
- data/doc/direct_s3.md +1 -0
- data/doc/external/articles.md +57 -45
- data/doc/external/extensions.md +41 -35
- data/doc/external/misc.md +23 -8
- data/doc/getting_started.md +177 -112
- data/doc/metadata.md +79 -43
- data/doc/multiple_files.md +6 -4
- data/doc/paperclip.md +119 -42
- data/doc/plugins/activerecord.md +1 -1
- data/doc/plugins/add_metadata.md +112 -35
- data/doc/plugins/atomic_helpers.md +41 -3
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +238 -171
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/download_endpoint.md +5 -5
- data/doc/plugins/dynamic_storage.md +1 -1
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +11 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +22 -10
- data/doc/plugins/mirroring.md +1 -1
- data/doc/plugins/persistence.md +11 -1
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +8 -3
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +12 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +4 -4
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/plugins/versions.md +7 -7
- data/doc/processing.md +290 -127
- data/doc/refile.md +39 -18
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/2.8.0.md +1 -1
- data/doc/release_notes/3.0.0.md +1 -1
- data/doc/release_notes/3.0.1.md +4 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/securing_uploads.md +3 -3
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +105 -82
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +97 -49
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +8 -8
- data/lib/shrine/attacher.rb +24 -14
- data/lib/shrine/attachment.rb +5 -5
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/activerecord.rb +1 -1
- data/lib/shrine/plugins/add_metadata.rb +18 -7
- data/lib/shrine/plugins/backgrounding.rb +2 -2
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +12 -7
- data/lib/shrine/plugins/derivatives.rb +61 -29
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/entity.rb +6 -6
- data/lib/shrine/plugins/mirroring.rb +8 -8
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +16 -4
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_attachment.rb +5 -0
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +22 -11
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +10 -5
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/memory.rb +5 -3
- data/lib/shrine/storage/s3.rb +117 -38
- data/lib/shrine/uploaded_file.rb +0 -1
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +7 -8
- metadata +25 -31
@@ -9,11 +9,11 @@ class Shrine
|
|
9
9
|
module Plugins
|
10
10
|
# Documentation can be found on https://shrinerb.com/docs/plugins/upload_endpoint
|
11
11
|
module UploadEndpoint
|
12
|
-
def self.load_dependencies(uploader,
|
12
|
+
def self.load_dependencies(uploader, **)
|
13
13
|
uploader.plugin :rack_file
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.configure(uploader, opts
|
16
|
+
def self.configure(uploader, **opts)
|
17
17
|
uploader.opts[:upload_endpoint] ||= {}
|
18
18
|
uploader.opts[:upload_endpoint].merge!(opts)
|
19
19
|
end
|
@@ -135,9 +135,14 @@ class Shrine
|
|
135
135
|
end
|
136
136
|
|
137
137
|
error!(400, "Upload Not Found") if value.nil?
|
138
|
-
error!(400, "Upload Not Valid") unless value.is_a?(Hash) && value[:tempfile]
|
139
138
|
|
140
|
-
|
139
|
+
if value.is_a?(Hash) && value[:tempfile]
|
140
|
+
@shrine_class.rack_file(value)
|
141
|
+
elsif %i[read rewind eof? close].all? { |m| value.respond_to?(m) }
|
142
|
+
value
|
143
|
+
else
|
144
|
+
error!(400, "Upload Not Valid")
|
145
|
+
end
|
141
146
|
end
|
142
147
|
|
143
148
|
# Returns a hash of information containing `:action` and `:request`
|
@@ -156,7 +161,7 @@ class Shrine
|
|
156
161
|
if @upload
|
157
162
|
@upload.call(io, context, request)
|
158
163
|
else
|
159
|
-
uploader.upload(io, context)
|
164
|
+
uploader.upload(io, **context)
|
160
165
|
end
|
161
166
|
end
|
162
167
|
|
@@ -4,9 +4,9 @@ class Shrine
|
|
4
4
|
module Plugins
|
5
5
|
# Documentation can be found on https://shrinerb.com/docs/plugins/upload_options
|
6
6
|
module UploadOptions
|
7
|
-
def self.configure(uploader,
|
7
|
+
def self.configure(uploader, **opts)
|
8
8
|
uploader.opts[:upload_options] ||= {}
|
9
|
-
uploader.opts[:upload_options].merge!(
|
9
|
+
uploader.opts[:upload_options].merge!(opts)
|
10
10
|
end
|
11
11
|
|
12
12
|
module InstanceMethods
|
@@ -4,9 +4,9 @@ class Shrine
|
|
4
4
|
module Plugins
|
5
5
|
# Documentation can be found on https://shrinerb.com/docs/plugins/url_options
|
6
6
|
module UrlOptions
|
7
|
-
def self.configure(uploader, **
|
7
|
+
def self.configure(uploader, **opts)
|
8
8
|
uploader.opts[:url_options] ||= {}
|
9
|
-
uploader.opts[:url_options].merge!(
|
9
|
+
uploader.opts[:url_options].merge!(opts)
|
10
10
|
end
|
11
11
|
|
12
12
|
module FileMethods
|
@@ -29,14 +29,16 @@ class Shrine
|
|
29
29
|
@errors = []
|
30
30
|
end
|
31
31
|
|
32
|
-
#
|
33
|
-
def
|
34
|
-
super(
|
32
|
+
# Performs validations after attaching cached file.
|
33
|
+
def attach_cached(value, validate: nil, **options)
|
34
|
+
result = super(value, validate: false, **options)
|
35
|
+
validation(validate)
|
36
|
+
result
|
35
37
|
end
|
36
38
|
|
37
|
-
# Performs validations after
|
38
|
-
def
|
39
|
-
result = super
|
39
|
+
# Performs validations after attaching file.
|
40
|
+
def attach(io, validate: nil, **options)
|
41
|
+
result = super(io, **options)
|
40
42
|
validation(validate)
|
41
43
|
result
|
42
44
|
end
|
@@ -52,7 +54,7 @@ class Shrine
|
|
52
54
|
# Calls validation appropriately based on the :validate value.
|
53
55
|
def validation(argument)
|
54
56
|
case argument
|
55
|
-
when Hash then validate(argument)
|
57
|
+
when Hash then validate(**argument)
|
56
58
|
when false then errors.clear # skip validation
|
57
59
|
else validate
|
58
60
|
end
|
@@ -35,7 +35,7 @@ class Shrine
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def call(io_factory = default_io_factory)
|
38
|
-
storage.upload(io_factory.call, id = "foo", {})
|
38
|
+
storage.upload(io_factory.call, id = "foo", shrine_metadata: { "foo" => "bar" })
|
39
39
|
|
40
40
|
lint_open(id)
|
41
41
|
lint_exists(id)
|
@@ -67,13 +67,13 @@ class Shrine
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def lint_open(id)
|
70
|
-
opened = storage.open(id
|
70
|
+
opened = storage.open(id)
|
71
71
|
error :open, "doesn't return a valid IO object" if !io?(opened)
|
72
72
|
error :open, "returns an empty IO object" if opened.read.empty?
|
73
73
|
opened.close
|
74
74
|
|
75
75
|
begin
|
76
|
-
storage.open(@nonexisting
|
76
|
+
storage.open(@nonexisting)
|
77
77
|
error :open, "should raise an exception on nonexisting file"
|
78
78
|
rescue Shrine::FileNotFound
|
79
79
|
rescue => exception
|
@@ -107,7 +107,7 @@ class Shrine
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def lint_presign(id)
|
110
|
-
data = storage.presign(id
|
110
|
+
data = storage.presign(id)
|
111
111
|
error :presign, "result should be a Hash" unless data.respond_to?(:to_h)
|
112
112
|
error :presign, "result should include :method key" unless data.to_h.key?(:method)
|
113
113
|
error :presign, "result should include :url key" unless data.to_h.key?(:url)
|
@@ -12,12 +12,14 @@ class Shrine
|
|
12
12
|
@store = store
|
13
13
|
end
|
14
14
|
|
15
|
-
def upload(io, id,
|
15
|
+
def upload(io, id, **)
|
16
16
|
store[id] = io.read
|
17
17
|
end
|
18
18
|
|
19
|
-
def open(id,
|
20
|
-
StringIO.new(store.fetch(id))
|
19
|
+
def open(id, **)
|
20
|
+
io = StringIO.new(store.fetch(id))
|
21
|
+
io.set_encoding(io.string.encoding) # Ruby 2.7.0 – https://bugs.ruby-lang.org/issues/16497
|
22
|
+
io
|
21
23
|
rescue KeyError
|
22
24
|
raise Shrine::FileNotFound, "file #{id.inspect} not found on storage"
|
23
25
|
end
|
data/lib/shrine/storage/s3.rb
CHANGED
@@ -9,6 +9,7 @@ require "down/chunked_io"
|
|
9
9
|
require "content_disposition"
|
10
10
|
|
11
11
|
require "uri"
|
12
|
+
require "tempfile"
|
12
13
|
|
13
14
|
class Shrine
|
14
15
|
module Storage
|
@@ -103,7 +104,7 @@ class Shrine
|
|
103
104
|
#
|
104
105
|
# [`Aws::S3::Object#get`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#get-instance_method
|
105
106
|
def open(id, rewindable: true, **options)
|
106
|
-
chunks, length =
|
107
|
+
chunks, length = get(id, **options)
|
107
108
|
|
108
109
|
Down::ChunkedIO.new(chunks: chunks, rewindable: rewindable, size: length)
|
109
110
|
rescue Aws::S3::Errors::NoSuchKey
|
@@ -179,25 +180,7 @@ class Shrine
|
|
179
180
|
options.merge!(@upload_options)
|
180
181
|
options.merge!(presign_options)
|
181
182
|
|
182
|
-
|
183
|
-
presigned_post = object(id).presigned_post(options)
|
184
|
-
|
185
|
-
{ method: method, url: presigned_post.url, fields: presigned_post.fields }
|
186
|
-
else
|
187
|
-
url = object(id).presigned_url(method, options)
|
188
|
-
|
189
|
-
# When any of these options are specified, the corresponding request
|
190
|
-
# headers must be included in the upload request.
|
191
|
-
headers = {}
|
192
|
-
headers["Content-Length"] = options[:content_length] if options[:content_length]
|
193
|
-
headers["Content-Type"] = options[:content_type] if options[:content_type]
|
194
|
-
headers["Content-Disposition"] = options[:content_disposition] if options[:content_disposition]
|
195
|
-
headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
|
196
|
-
headers["Content-Language"] = options[:content_language] if options[:content_language]
|
197
|
-
headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
|
198
|
-
|
199
|
-
{ method: method, url: url, headers: headers }
|
200
|
-
end
|
183
|
+
send(:"presign_#{method}", id, options)
|
201
184
|
end
|
202
185
|
|
203
186
|
# Deletes the file from the storage.
|
@@ -230,11 +213,22 @@ class Shrine
|
|
230
213
|
|
231
214
|
# Returns an `Aws::S3::Object` for the given id.
|
232
215
|
def object(id)
|
233
|
-
bucket.object(
|
216
|
+
bucket.object(object_key(id))
|
234
217
|
end
|
235
218
|
|
236
219
|
private
|
237
220
|
|
221
|
+
# Uploads the file to S3. Uses multipart upload for large files.
|
222
|
+
def put(io, id, **options)
|
223
|
+
if io.respond_to?(:size) && io.size && io.size <= @multipart_threshold[:upload]
|
224
|
+
object(id).put(body: io, **options)
|
225
|
+
else # multipart upload
|
226
|
+
object(id).upload_stream(part_size: part_size(io), **options) do |write_stream|
|
227
|
+
IO.copy_stream(io, write_stream)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
238
232
|
# Copies an existing S3 object to a new location. Uses multipart copy for
|
239
233
|
# large files.
|
240
234
|
def copy(io, id, **copy_options)
|
@@ -250,15 +244,28 @@ class Shrine
|
|
250
244
|
object(id).copy_from(io.storage.object(io.id), **options)
|
251
245
|
end
|
252
246
|
|
253
|
-
#
|
254
|
-
def
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
247
|
+
# Generates parameters for a POST upload request.
|
248
|
+
def presign_post(id, options)
|
249
|
+
presigned_post = object(id).presigned_post(options)
|
250
|
+
|
251
|
+
{ method: :post, url: presigned_post.url, fields: presigned_post.fields }
|
252
|
+
end
|
253
|
+
|
254
|
+
# Generates parameters for a PUT upload request.
|
255
|
+
def presign_put(id, options)
|
256
|
+
url = object(id).presigned_url(:put, options)
|
257
|
+
|
258
|
+
# When any of these options are specified, the corresponding request
|
259
|
+
# headers must be included in the upload request.
|
260
|
+
headers = {}
|
261
|
+
headers["Content-Length"] = options[:content_length] if options[:content_length]
|
262
|
+
headers["Content-Type"] = options[:content_type] if options[:content_type]
|
263
|
+
headers["Content-Disposition"] = options[:content_disposition] if options[:content_disposition]
|
264
|
+
headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
|
265
|
+
headers["Content-Language"] = options[:content_language] if options[:content_language]
|
266
|
+
headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
|
267
|
+
|
268
|
+
{ method: :put, url: url, headers: headers }
|
262
269
|
end
|
263
270
|
|
264
271
|
# Determins the part size that should be used when uploading the given IO
|
@@ -274,17 +281,38 @@ class Shrine
|
|
274
281
|
end
|
275
282
|
|
276
283
|
# Aws::S3::Object#get doesn't allow us to get the content length of the
|
277
|
-
# object before
|
278
|
-
|
279
|
-
|
284
|
+
# object before all content is downloaded, so we hack our way around it.
|
285
|
+
# This way get the content length without an additional HEAD request.
|
286
|
+
if Gem::Version.new(Aws::CORE_GEM_VERSION) >= Gem::Version.new("3.104.0")
|
287
|
+
def get(id, **params)
|
288
|
+
enum = object(id).enum_for(:get, **params)
|
289
|
+
|
290
|
+
begin
|
291
|
+
content_length = Integer(enum.peek.last["content-length"])
|
292
|
+
rescue StopIteration
|
293
|
+
content_length = 0
|
294
|
+
end
|
280
295
|
|
281
|
-
|
282
|
-
|
296
|
+
chunks = Enumerator.new { |y| loop { y << enum.next.first } }
|
297
|
+
|
298
|
+
[chunks, content_length]
|
299
|
+
end
|
300
|
+
else
|
301
|
+
def get(id, **params)
|
302
|
+
req = client.build_request(:get_object, bucket: bucket.name, key: object_key(id), **params)
|
303
|
+
|
304
|
+
body = req.enum_for(:send_request)
|
305
|
+
begin
|
306
|
+
body.peek # start the request
|
307
|
+
rescue StopIteration
|
308
|
+
# the S3 object is empty
|
309
|
+
end
|
283
310
|
|
284
|
-
|
285
|
-
|
311
|
+
content_length = Integer(req.context.http_response.headers["Content-Length"])
|
312
|
+
chunks = Enumerator.new { |y| loop { y << body.next } }
|
286
313
|
|
287
|
-
|
314
|
+
[chunks, content_length]
|
315
|
+
end
|
288
316
|
end
|
289
317
|
|
290
318
|
# The file is copyable if it's on S3 and on the same Amazon account.
|
@@ -302,6 +330,57 @@ class Shrine
|
|
302
330
|
bucket.delete_objects(delete: delete_params)
|
303
331
|
end
|
304
332
|
end
|
333
|
+
|
334
|
+
# Returns object key with potential prefix.
|
335
|
+
def object_key(id)
|
336
|
+
[*prefix, id].join("/")
|
337
|
+
end
|
338
|
+
|
339
|
+
# Adds support for Aws::S3::Encryption::Client.
|
340
|
+
module ClientSideEncryption
|
341
|
+
attr_reader :encryption_client
|
342
|
+
|
343
|
+
# Save the encryption client and continue initialization with normal
|
344
|
+
# client.
|
345
|
+
def initialize(client: nil, **options)
|
346
|
+
return super unless client.class.name.start_with?("Aws::S3::Encryption")
|
347
|
+
|
348
|
+
super(client: client.client, **options)
|
349
|
+
@encryption_client = client
|
350
|
+
end
|
351
|
+
|
352
|
+
private
|
353
|
+
|
354
|
+
# Encryption client doesn't support multipart uploads, so we always use
|
355
|
+
# #put_object.
|
356
|
+
def put(io, id, **options)
|
357
|
+
return super unless encryption_client
|
358
|
+
|
359
|
+
encryption_client.put_object(body: io, bucket: bucket.name, key: object_key(id), **options)
|
360
|
+
end
|
361
|
+
|
362
|
+
def get(id, **options)
|
363
|
+
return super unless encryption_client
|
364
|
+
|
365
|
+
# Encryption client v2 warns against streaming download, so we first
|
366
|
+
# download all content into a file.
|
367
|
+
tempfile = Tempfile.new("shrine-s3", binmode: true)
|
368
|
+
response = encryption_client.get_object(response_target: tempfile, bucket: bucket.name, key: object_key(id), **options)
|
369
|
+
tempfile.rewind
|
370
|
+
|
371
|
+
chunks = Enumerator.new do |yielder|
|
372
|
+
begin
|
373
|
+
yielder << tempfile.read(16*1024) until tempfile.eof?
|
374
|
+
ensure
|
375
|
+
tempfile.close!
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
[chunks, tempfile.size]
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
prepend ClientSideEncryption
|
305
384
|
end
|
306
385
|
end
|
307
386
|
end
|
data/lib/shrine/uploaded_file.rb
CHANGED
data/lib/shrine/version.rb
CHANGED
data/shrine.gemspec
CHANGED
@@ -33,18 +33,17 @@ direct uploads for fully asynchronous user experience.
|
|
33
33
|
gem.files = Dir["README.md", "LICENSE.txt", "CHANGELOG.md", "lib/**/*.rb", "shrine.gemspec", "doc/**/*.md"]
|
34
34
|
gem.require_path = "lib"
|
35
35
|
|
36
|
-
gem.add_dependency "down", "~> 5.
|
36
|
+
gem.add_dependency "down", "~> 5.1"
|
37
37
|
gem.add_dependency "content_disposition", "~> 1.0"
|
38
38
|
|
39
39
|
# general testing helpers
|
40
40
|
gem.add_development_dependency "rake", ">= 11.1"
|
41
41
|
gem.add_development_dependency "minitest", "~> 5.8"
|
42
|
-
gem.add_development_dependency "mocha", "~> 1.
|
43
|
-
gem.add_development_dependency "dry-initializer"
|
42
|
+
gem.add_development_dependency "mocha", "~> 1.11"
|
44
43
|
|
45
44
|
# for endpoint plugins
|
46
45
|
gem.add_development_dependency "rack", "~> 2.0"
|
47
|
-
gem.add_development_dependency "http-form_data", "~> 2.
|
46
|
+
gem.add_development_dependency "http-form_data", "~> 2.2"
|
48
47
|
gem.add_development_dependency "rack-test_app"
|
49
48
|
|
50
49
|
# for determine_mime_type plugin
|
@@ -62,15 +61,15 @@ direct uploads for fully asynchronous user experience.
|
|
62
61
|
gem.add_development_dependency "ruby-vips", "~> 2.0" unless ENV["CI"]
|
63
62
|
|
64
63
|
# for S3 storage
|
65
|
-
gem.add_development_dependency "aws-sdk-s3", "~> 1.
|
64
|
+
gem.add_development_dependency "aws-sdk-s3", "~> 1.69"
|
66
65
|
gem.add_development_dependency "aws-sdk-core", "~> 3.23"
|
67
66
|
|
68
67
|
# for instrumentation plugin
|
69
68
|
gem.add_development_dependency "dry-monitor"
|
70
|
-
gem.add_development_dependency "activesupport", "~> 5.2
|
69
|
+
gem.add_development_dependency "activesupport", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
|
71
70
|
|
72
71
|
# for ORM plugins
|
73
72
|
gem.add_development_dependency "sequel"
|
74
|
-
gem.add_development_dependency "activerecord", "~> 5.2
|
75
|
-
gem.add_development_dependency "sqlite3", "~> 1.
|
73
|
+
gem.add_development_dependency "activerecord", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
|
74
|
+
gem.add_development_dependency "sqlite3", "~> 1.4" unless RUBY_ENGINE == "jruby"
|
76
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shrine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: down
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '5.
|
19
|
+
version: '5.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '5.
|
26
|
+
version: '5.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: content_disposition
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,28 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '1.
|
75
|
+
version: '1.11'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '1.
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: dry-initializer
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
82
|
+
version: '1.11'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: rack
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +100,14 @@ dependencies:
|
|
114
100
|
requirements:
|
115
101
|
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: '2.
|
103
|
+
version: '2.2'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
108
|
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '2.
|
110
|
+
version: '2.2'
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: rack-test_app
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -254,14 +240,14 @@ dependencies:
|
|
254
240
|
requirements:
|
255
241
|
- - "~>"
|
256
242
|
- !ruby/object:Gem::Version
|
257
|
-
version: '1.
|
243
|
+
version: '1.69'
|
258
244
|
type: :development
|
259
245
|
prerelease: false
|
260
246
|
version_requirements: !ruby/object:Gem::Requirement
|
261
247
|
requirements:
|
262
248
|
- - "~>"
|
263
249
|
- !ruby/object:Gem::Version
|
264
|
-
version: '1.
|
250
|
+
version: '1.69'
|
265
251
|
- !ruby/object:Gem::Dependency
|
266
252
|
name: aws-sdk-core
|
267
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -296,14 +282,14 @@ dependencies:
|
|
296
282
|
requirements:
|
297
283
|
- - "~>"
|
298
284
|
- !ruby/object:Gem::Version
|
299
|
-
version:
|
285
|
+
version: '6.0'
|
300
286
|
type: :development
|
301
287
|
prerelease: false
|
302
288
|
version_requirements: !ruby/object:Gem::Requirement
|
303
289
|
requirements:
|
304
290
|
- - "~>"
|
305
291
|
- !ruby/object:Gem::Version
|
306
|
-
version:
|
292
|
+
version: '6.0'
|
307
293
|
- !ruby/object:Gem::Dependency
|
308
294
|
name: sequel
|
309
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,28 +310,28 @@ dependencies:
|
|
324
310
|
requirements:
|
325
311
|
- - "~>"
|
326
312
|
- !ruby/object:Gem::Version
|
327
|
-
version:
|
313
|
+
version: '6.0'
|
328
314
|
type: :development
|
329
315
|
prerelease: false
|
330
316
|
version_requirements: !ruby/object:Gem::Requirement
|
331
317
|
requirements:
|
332
318
|
- - "~>"
|
333
319
|
- !ruby/object:Gem::Version
|
334
|
-
version:
|
320
|
+
version: '6.0'
|
335
321
|
- !ruby/object:Gem::Dependency
|
336
322
|
name: sqlite3
|
337
323
|
requirement: !ruby/object:Gem::Requirement
|
338
324
|
requirements:
|
339
325
|
- - "~>"
|
340
326
|
- !ruby/object:Gem::Version
|
341
|
-
version: 1.
|
327
|
+
version: '1.4'
|
342
328
|
type: :development
|
343
329
|
prerelease: false
|
344
330
|
version_requirements: !ruby/object:Gem::Requirement
|
345
331
|
requirements:
|
346
332
|
- - "~>"
|
347
333
|
- !ruby/object:Gem::Version
|
348
|
-
version: 1.
|
334
|
+
version: '1.4'
|
349
335
|
description: |
|
350
336
|
Shrine is a toolkit for file attachments in Ruby applications. It supports
|
351
337
|
uploading, downloading, processing and deleting IO objects, backed by various
|
@@ -424,6 +410,7 @@ files:
|
|
424
410
|
- doc/plugins/signature.md
|
425
411
|
- doc/plugins/store_dimensions.md
|
426
412
|
- doc/plugins/tempfile.md
|
413
|
+
- doc/plugins/type_predicates.md
|
427
414
|
- doc/plugins/upload_endpoint.md
|
428
415
|
- doc/plugins/upload_options.md
|
429
416
|
- doc/plugins/url_options.md
|
@@ -467,9 +454,15 @@ files:
|
|
467
454
|
- doc/release_notes/2.9.0.md
|
468
455
|
- doc/release_notes/3.0.0.md
|
469
456
|
- doc/release_notes/3.0.1.md
|
457
|
+
- doc/release_notes/3.1.0.md
|
458
|
+
- doc/release_notes/3.2.0.md
|
459
|
+
- doc/release_notes/3.2.1.md
|
460
|
+
- doc/release_notes/3.2.2.md
|
461
|
+
- doc/release_notes/3.3.0.md
|
470
462
|
- doc/retrieving_uploads.md
|
471
463
|
- doc/securing_uploads.md
|
472
464
|
- doc/storage/file_system.md
|
465
|
+
- doc/storage/memory.md
|
473
466
|
- doc/storage/s3.md
|
474
467
|
- doc/testing.md
|
475
468
|
- doc/upgrading_to_3.md
|
@@ -522,6 +515,7 @@ files:
|
|
522
515
|
- lib/shrine/plugins/signature.rb
|
523
516
|
- lib/shrine/plugins/store_dimensions.rb
|
524
517
|
- lib/shrine/plugins/tempfile.rb
|
518
|
+
- lib/shrine/plugins/type_predicates.rb
|
525
519
|
- lib/shrine/plugins/upload_endpoint.rb
|
526
520
|
- lib/shrine/plugins/upload_options.rb
|
527
521
|
- lib/shrine/plugins/url_options.rb
|
@@ -559,7 +553,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
559
553
|
- !ruby/object:Gem::Version
|
560
554
|
version: '0'
|
561
555
|
requirements: []
|
562
|
-
rubygems_version: 3.
|
556
|
+
rubygems_version: 3.1.4
|
563
557
|
signing_key:
|
564
558
|
specification_version: 4
|
565
559
|
summary: Toolkit for file attachments in Ruby applications
|