shrine 3.4.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -47,6 +47,10 @@ class Shrine
47
47
  # `{upload: 15*1024*1024, copy: 100*1024*1024}` (15MB for upload
48
48
  # requests, 100MB for copy requests).
49
49
  #
50
+ # :max_multipart_parts
51
+ # : Limits the number of parts if parellized multipart upload/copy is used.
52
+ # Defaults to 10_000.
53
+ #
50
54
  # In addition to specifying the `:bucket`, you'll also need to provide
51
55
  # AWS credentials. The most common way is to provide them directly via
52
56
  # `:access_key_id`, `:secret_access_key`, and `:region` options. But you
@@ -58,7 +62,7 @@ class Shrine
58
62
  # [`Aws::S3::Bucket#presigned_post`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
59
63
  # [`Aws::S3::Client#initialize`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#initialize-instance_method
60
64
  # [configuring AWS SDK]: https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html
61
- def initialize(bucket:, client: nil, prefix: nil, upload_options: {}, multipart_threshold: {}, signer: nil, public: nil, **s3_options)
65
+ def initialize(bucket:, client: nil, prefix: nil, upload_options: {}, multipart_threshold: {}, max_multipart_parts: nil, signer: nil, public: nil, **s3_options)
62
66
  raise ArgumentError, "the :bucket option is nil" unless bucket
63
67
 
64
68
  @client = client || Aws::S3::Client.new(**s3_options)
@@ -66,6 +70,7 @@ class Shrine
66
70
  @prefix = prefix
67
71
  @upload_options = upload_options
68
72
  @multipart_threshold = MULTIPART_THRESHOLD.merge(multipart_threshold)
73
+ @max_multipart_parts = max_multipart_parts || MAX_MULTIPART_PARTS
69
74
  @signer = signer
70
75
  @public = public
71
76
  end
@@ -98,15 +103,16 @@ class Shrine
98
103
  # Returns a `Down::ChunkedIO` object that downloads S3 object content
99
104
  # on-demand. By default, read content will be cached onto disk so that
100
105
  # it can be rewinded, but if you don't need that you can pass
101
- # `rewindable: false`.
106
+ # `rewindable: false`. A required character encoding can be passed in
107
+ # `encoding`; the default is `Encoding::BINARY` via `Down::ChunkedIO`.
102
108
  #
103
109
  # Any additional options are forwarded to [`Aws::S3::Object#get`].
104
110
  #
105
111
  # [`Aws::S3::Object#get`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#get-instance_method
106
- def open(id, rewindable: true, **options)
112
+ def open(id, rewindable: true, encoding: nil, **options)
107
113
  chunks, length = get(id, **options)
108
114
 
109
- Down::ChunkedIO.new(chunks: chunks, rewindable: rewindable, size: length)
115
+ Down::ChunkedIO.new(chunks: chunks, rewindable: rewindable, size: length, encoding: encoding)
110
116
  rescue Aws::S3::Errors::NoSuchKey
111
117
  raise Shrine::FileNotFound, "file #{id.inspect} not found on storage"
112
118
  end
@@ -232,7 +238,11 @@ class Shrine
232
238
  # Copies an existing S3 object to a new location. Uses multipart copy for
233
239
  # large files.
234
240
  def copy(io, id, **copy_options)
235
- options = { metadata_directive: "REPLACE" } # don't inherit source object metadata
241
+ # don't inherit source object metadata or AWS tags
242
+ options = {
243
+ metadata_directive: "REPLACE",
244
+ tagging_directive: "REPLACE"
245
+ }
236
246
 
237
247
  if io.size && io.size >= @multipart_threshold[:copy]
238
248
  # pass :content_length on multipart copy to avoid an additional HEAD request
@@ -273,10 +283,10 @@ class Shrine
273
283
  def part_size(io)
274
284
  return unless io.respond_to?(:size) && io.size
275
285
 
276
- if io.size <= MIN_PART_SIZE * MAX_MULTIPART_PARTS # <= 50 GB
286
+ if io.size <= MIN_PART_SIZE * @max_multipart_parts # <= 50 GB
277
287
  MIN_PART_SIZE
278
288
  else # > 50 GB
279
- (io.size.to_f / MAX_MULTIPART_PARTS).ceil
289
+ (io.size.to_f / @max_multipart_parts).ceil
280
290
  end
281
291
  end
282
292
 
@@ -50,8 +50,9 @@ class Shrine
50
50
  # The extension derived from #id if present, otherwise it's derived
51
51
  # from #original_filename.
52
52
  def extension
53
- result = File.extname(id)[1..-1] || File.extname(original_filename.to_s)[1..-1]
54
- result.sub!(/\?.+$/, "") if result && id =~ URI::regexp # strip query params for shrine-url
53
+ identifier = id =~ URI::DEFAULT_PARSER.make_regexp ? id.sub(/\?.+$/, "") : id # strip query params for shrine-url
54
+ result = File.extname(identifier)[1..-1]
55
+ result ||= File.extname(original_filename.to_s)[1..-1]
55
56
  result.downcase if result
56
57
  end
57
58
 
@@ -7,7 +7,7 @@ class Shrine
7
7
 
8
8
  module VERSION
9
9
  MAJOR = 3
10
- MINOR = 4
10
+ MINOR = 5
11
11
  TINY = 0
12
12
  PRE = nil
13
13
 
data/lib/shrine.rb CHANGED
@@ -252,7 +252,7 @@ class Shrine
252
252
  def extract_filename(io)
253
253
  if io.respond_to?(:original_filename)
254
254
  io.original_filename
255
- elsif io.respond_to?(:path)
255
+ elsif io.respond_to?(:path) && io.path
256
256
  File.basename(io.path)
257
257
  end
258
258
  end
data/shrine.gemspec CHANGED
@@ -67,10 +67,10 @@ direct uploads for fully asynchronous user experience.
67
67
 
68
68
  # for instrumentation plugin
69
69
  gem.add_development_dependency "dry-monitor"
70
- gem.add_development_dependency "activesupport", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
70
+ gem.add_development_dependency "activesupport", RUBY_VERSION >= "2.7" ? "~> 7.0" : RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
71
71
 
72
72
  # for ORM plugins
73
73
  gem.add_development_dependency "sequel"
74
- gem.add_development_dependency "activerecord", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
74
+ gem.add_development_dependency "activerecord", RUBY_VERSION >= "2.7" ? "~> 7.0" : RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
75
75
  gem.add_development_dependency "sqlite3", "~> 1.4" unless RUBY_ENGINE == "jruby"
76
76
  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.4.0
4
+ version: 3.5.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: 2021-06-14 00:00:00.000000000 Z
11
+ date: 2023-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -296,14 +296,14 @@ dependencies:
296
296
  requirements:
297
297
  - - "~>"
298
298
  - !ruby/object:Gem::Version
299
- version: '6.0'
299
+ version: '7.0'
300
300
  type: :development
301
301
  prerelease: false
302
302
  version_requirements: !ruby/object:Gem::Requirement
303
303
  requirements:
304
304
  - - "~>"
305
305
  - !ruby/object:Gem::Version
306
- version: '6.0'
306
+ version: '7.0'
307
307
  - !ruby/object:Gem::Dependency
308
308
  name: sequel
309
309
  requirement: !ruby/object:Gem::Requirement
@@ -324,14 +324,14 @@ dependencies:
324
324
  requirements:
325
325
  - - "~>"
326
326
  - !ruby/object:Gem::Version
327
- version: '6.0'
327
+ version: '7.0'
328
328
  type: :development
329
329
  prerelease: false
330
330
  version_requirements: !ruby/object:Gem::Requirement
331
331
  requirements:
332
332
  - - "~>"
333
333
  - !ruby/object:Gem::Version
334
- version: '6.0'
334
+ version: '7.0'
335
335
  - !ruby/object:Gem::Dependency
336
336
  name: sqlite3
337
337
  requirement: !ruby/object:Gem::Requirement
@@ -474,6 +474,7 @@ files:
474
474
  - doc/release_notes/3.2.2.md
475
475
  - doc/release_notes/3.3.0.md
476
476
  - doc/release_notes/3.4.0.md
477
+ - doc/release_notes/3.5.0.md
477
478
  - doc/retrieving_uploads.md
478
479
  - doc/securing_uploads.md
479
480
  - doc/storage/file_system.md
@@ -568,7 +569,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
568
569
  - !ruby/object:Gem::Version
569
570
  version: '0'
570
571
  requirements: []
571
- rubygems_version: 3.2.15
572
+ rubygems_version: 3.4.12
572
573
  signing_key:
573
574
  specification_version: 4
574
575
  summary: Toolkit for file attachments in Ruby applications