shrine 3.6.0 → 3.7.1

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/doc/changing_derivatives.md +2 -1
  4. data/doc/changing_location.md +17 -5
  5. data/doc/getting_started.md +4 -2
  6. data/doc/plugins/derivation_endpoint.md +15 -1
  7. data/doc/plugins/derivatives.md +2 -1
  8. data/doc/plugins/download_endpoint.md +16 -4
  9. data/doc/plugins/rack_response.md +9 -0
  10. data/doc/plugins/refresh_metadata.md +20 -0
  11. data/doc/plugins/signature.md +8 -6
  12. data/doc/processing.md +5 -3
  13. data/doc/release_notes/3.7.0.md +75 -0
  14. data/doc/release_notes/3.7.1.md +13 -0
  15. data/lib/shrine/attacher.rb +21 -21
  16. data/lib/shrine/attachment.rb +2 -2
  17. data/lib/shrine/plugins/_persistence.rb +1 -1
  18. data/lib/shrine/plugins/_urlsafe_serialization.rb +4 -4
  19. data/lib/shrine/plugins/add_metadata.rb +2 -4
  20. data/lib/shrine/plugins/atomic_helpers.rb +7 -7
  21. data/lib/shrine/plugins/backgrounding.rb +9 -9
  22. data/lib/shrine/plugins/column.rb +6 -4
  23. data/lib/shrine/plugins/data_uri.rb +1 -1
  24. data/lib/shrine/plugins/default_url.rb +4 -4
  25. data/lib/shrine/plugins/delete_raw.rb +2 -2
  26. data/lib/shrine/plugins/derivation_endpoint.rb +29 -27
  27. data/lib/shrine/plugins/derivatives.rb +5 -1
  28. data/lib/shrine/plugins/download_endpoint.rb +62 -10
  29. data/lib/shrine/plugins/entity.rb +7 -7
  30. data/lib/shrine/plugins/infer_extension.rb +1 -1
  31. data/lib/shrine/plugins/instrumentation.rb +8 -8
  32. data/lib/shrine/plugins/metadata_attributes.rb +1 -1
  33. data/lib/shrine/plugins/mirroring.rb +10 -10
  34. data/lib/shrine/plugins/model.rb +9 -9
  35. data/lib/shrine/plugins/presign_endpoint.rb +4 -4
  36. data/lib/shrine/plugins/pretty_location.rb +2 -2
  37. data/lib/shrine/plugins/processing.rb +3 -3
  38. data/lib/shrine/plugins/rack_file.rb +2 -2
  39. data/lib/shrine/plugins/rack_response.rb +6 -6
  40. data/lib/shrine/plugins/refresh_metadata.rb +6 -6
  41. data/lib/shrine/plugins/remote_url.rb +4 -4
  42. data/lib/shrine/plugins/restore_cached_data.rb +3 -3
  43. data/lib/shrine/plugins/signature.rb +2 -2
  44. data/lib/shrine/plugins/store_dimensions.rb +2 -2
  45. data/lib/shrine/plugins/upload_endpoint.rb +4 -4
  46. data/lib/shrine/plugins/upload_options.rb +1 -1
  47. data/lib/shrine/plugins/validation.rb +8 -8
  48. data/lib/shrine/plugins/validation_helpers.rb +1 -1
  49. data/lib/shrine/plugins/versions.rb +10 -10
  50. data/lib/shrine/plugins.rb +6 -14
  51. data/lib/shrine/storage/file_system.rb +4 -17
  52. data/lib/shrine/storage/linter.rb +8 -8
  53. data/lib/shrine/storage/memory.rb +1 -3
  54. data/lib/shrine/storage/s3.rb +45 -37
  55. data/lib/shrine/uploaded_file.rb +20 -18
  56. data/lib/shrine/version.rb +2 -2
  57. data/lib/shrine.rb +18 -18
  58. data/shrine.gemspec +6 -6
  59. metadata +16 -17
@@ -68,10 +68,11 @@ class Shrine
68
68
  # [`Aws::S3::Bucket#presigned_post`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
69
69
  # [`Aws::S3::Client#initialize`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#initialize-instance_method
70
70
  # [configuring AWS SDK]: https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html
71
- def initialize(bucket:, client: nil, prefix: nil, upload_options: {}, multipart_threshold: {}, max_multipart_parts: nil, signer: nil, public: nil, copy_options: COPY_OPTIONS, **s3_options)
71
+ def initialize(bucket:, client: nil, prefix: nil, upload_options: {}, multipart_threshold: {}, max_multipart_parts: nil, signer: nil, public: nil, copy_options: COPY_OPTIONS, **)
72
72
  raise ArgumentError, "the :bucket option is nil" unless bucket
73
73
 
74
- @client = client || Aws::S3::Client.new(**s3_options)
74
+ @client = client || Aws::S3::Client.new(**)
75
+ @transfer_manager = Aws::S3::TransferManager.new(client: @client) if defined?(Aws::S3::TransferManager)
75
76
  @bucket = Aws::S3::Bucket.new(name: bucket, client: @client)
76
77
  @prefix = prefix
77
78
  @upload_options = upload_options
@@ -97,8 +98,7 @@ class Shrine
97
98
  options[:content_disposition] = ContentDisposition.inline(filename) if filename
98
99
  options[:acl] = "public-read" if public
99
100
 
100
- options.merge!(@upload_options)
101
- options.merge!(upload_options)
101
+ options.merge!(@upload_options, upload_options)
102
102
 
103
103
  if copyable?(io)
104
104
  copy(io, id, **options)
@@ -116,8 +116,8 @@ class Shrine
116
116
  # Any additional options are forwarded to [`Aws::S3::Object#get`].
117
117
  #
118
118
  # [`Aws::S3::Object#get`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#get-instance_method
119
- def open(id, rewindable: true, encoding: nil, **options)
120
- chunks, length = get(id, **options)
119
+ def open(id, rewindable: true, encoding: nil, **)
120
+ chunks, length = get(id, **)
121
121
 
122
122
  Down::ChunkedIO.new(chunks: chunks, rewindable: rewindable, size: length, encoding: encoding)
123
123
  rescue Aws::S3::Errors::NoSuchKey
@@ -145,11 +145,11 @@ class Shrine
145
145
  #
146
146
  # [`Aws::S3::Object#presigned_url`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
147
147
  # [`Aws::S3::Object#public_url`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#public_url-instance_method
148
- def url(id, public: self.public, host: nil, **options)
148
+ def url(id, public: self.public, host: nil, **)
149
149
  if public || signer
150
- url = object(id).public_url(**options)
150
+ url = object(id).public_url(**)
151
151
  else
152
- url = object(id).presigned_url(:get, **options)
152
+ url = object(id).presigned_url(:get, **)
153
153
  end
154
154
 
155
155
  if host
@@ -159,7 +159,7 @@ class Shrine
159
159
  end
160
160
 
161
161
  if signer
162
- url = signer.call(url, **options)
162
+ url = signer.call(url, **)
163
163
  end
164
164
 
165
165
  url
@@ -190,8 +190,7 @@ class Shrine
190
190
  options = {}
191
191
  options[:acl] = "public-read" if public
192
192
 
193
- options.merge!(@upload_options)
194
- options.merge!(presign_options)
193
+ options.merge!(@upload_options, presign_options)
195
194
 
196
195
  send(:"presign_#{method}", id, options)
197
196
  end
@@ -231,12 +230,21 @@ class Shrine
231
230
 
232
231
  private
233
232
 
234
- # Uploads the file to S3. Uses multipart upload for large files.
235
- def put(io, id, **options)
236
- if io.respond_to?(:size) && io.size && io.size <= @multipart_threshold[:upload]
237
- object(id).put(body: io, **options)
238
- else # multipart upload
239
- object(id).upload_stream(part_size: part_size(io), **options) do |write_stream|
233
+ # Upload the file to S3.
234
+ # Uses @transfer_manager, if defined, for any size upload.
235
+ # Falls back to the original code using the older, now depricated
236
+ # AWS APIs for users of older version of the AWS Gem.
237
+ # for multipart uploads of large files.
238
+ def put(io, id, **)
239
+ if @transfer_manager
240
+ @transfer_manager.upload_stream(bucket: bucket.name, key: object_key(id), part_size: part_size(io), **) do |write_stream|
241
+ IO.copy_stream(io, write_stream)
242
+ end
243
+ elsif io.respond_to?(:size) && io.size && io.size <= @multipart_threshold[:upload]
244
+ object(id).put(body: io, **)
245
+ else
246
+ # multipart upload old API
247
+ object(id).upload_stream(part_size: part_size(io), **) do |write_stream|
240
248
  IO.copy_stream(io, write_stream)
241
249
  end
242
250
  end
@@ -255,8 +263,7 @@ class Shrine
255
263
  options.merge!(multipart_copy: true, content_length: io.size)
256
264
  end
257
265
 
258
- options.merge!(@copy_options)
259
- options.merge!(copy_options)
266
+ options.merge!(@copy_options, copy_options)
260
267
 
261
268
  object(id).copy_from(io.storage.object(io.id), **options)
262
269
  end
@@ -274,13 +281,14 @@ class Shrine
274
281
 
275
282
  # When any of these options are specified, the corresponding request
276
283
  # headers must be included in the upload request.
277
- headers = {}
278
- headers["Content-Length"] = options[:content_length] if options[:content_length]
279
- headers["Content-Type"] = options[:content_type] if options[:content_type]
280
- headers["Content-Disposition"] = options[:content_disposition] if options[:content_disposition]
281
- headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
282
- headers["Content-Language"] = options[:content_language] if options[:content_language]
283
- headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
284
+ headers = {
285
+ "Content-Length" => options[:content_length],
286
+ "Content-Type" => options[:content_type],
287
+ "Content-Disposition" => options[:content_disposition],
288
+ "Content-Encoding" => options[:content_encoding],
289
+ "Content-Language" => options[:content_language],
290
+ "Content-MD5" => options[:content_md5],
291
+ }.compact
284
292
 
285
293
  { method: :put, url: url, headers: headers }
286
294
  end
@@ -301,8 +309,8 @@ class Shrine
301
309
  # object before all content is downloaded, so we hack our way around it.
302
310
  # This way get the content length without an additional HEAD request.
303
311
  if Gem::Version.new(Aws::CORE_GEM_VERSION) >= Gem::Version.new("3.104.0")
304
- def get(id, **params)
305
- enum = object(id).enum_for(:get, **params)
312
+ def get(id, **)
313
+ enum = object(id).enum_for(:get, **)
306
314
 
307
315
  begin
308
316
  content_length = Integer(enum.peek.last["content-length"])
@@ -315,8 +323,8 @@ class Shrine
315
323
  [chunks, content_length]
316
324
  end
317
325
  else
318
- def get(id, **params)
319
- req = client.build_request(:get_object, bucket: bucket.name, key: object_key(id), **params)
326
+ def get(id, **)
327
+ req = client.build_request(:get_object, bucket: bucket.name, key: object_key(id), **)
320
328
 
321
329
  body = req.enum_for(:send_request)
322
330
  begin
@@ -359,10 +367,10 @@ class Shrine
359
367
 
360
368
  # Save the encryption client and continue initialization with normal
361
369
  # client.
362
- def initialize(client: nil, **options)
370
+ def initialize(client: nil, **)
363
371
  return super unless client.class.name.start_with?("Aws::S3::Encryption")
364
372
 
365
- super(client: client.client, **options)
373
+ super(client: client.client, **)
366
374
  @encryption_client = client
367
375
  end
368
376
 
@@ -370,19 +378,19 @@ class Shrine
370
378
 
371
379
  # Encryption client doesn't support multipart uploads, so we always use
372
380
  # #put_object.
373
- def put(io, id, **options)
381
+ def put(io, id, **)
374
382
  return super unless encryption_client
375
383
 
376
- encryption_client.put_object(body: io, bucket: bucket.name, key: object_key(id), **options)
384
+ encryption_client.put_object(body: io, bucket: bucket.name, key: object_key(id), **)
377
385
  end
378
386
 
379
- def get(id, **options)
387
+ def get(id, **)
380
388
  return super unless encryption_client
381
389
 
382
390
  # Encryption client v2 warns against streaming download, so we first
383
391
  # download all content into a file.
384
392
  tempfile = Tempfile.new("shrine-s3", binmode: true)
385
- response = encryption_client.get_object(response_target: tempfile, bucket: bucket.name, key: object_key(id), **options)
393
+ response = encryption_client.get_object(response_target: tempfile, bucket: bucket.name, key: object_key(id), **)
386
394
  tempfile.rewind
387
395
 
388
396
  chunks = Enumerator.new do |yielder|
@@ -22,6 +22,8 @@ class Shrine
22
22
  end
23
23
 
24
24
  module InstanceMethods
25
+ RFC2396_PARSER = URI::RFC2396_Parser.new
26
+
25
27
  # The location where the file was uploaded to the storage.
26
28
  attr_reader :id
27
29
 
@@ -50,7 +52,7 @@ class Shrine
50
52
  # The extension derived from #id if present, otherwise it's derived
51
53
  # from #original_filename.
52
54
  def extension
53
- identifier = id =~ URI::DEFAULT_PARSER.make_regexp ? id.sub(/\?.+$/, "") : id # strip query params for shrine-url
55
+ identifier = id =~ RFC2396_PARSER.make_regexp ? id.sub(/\?.+$/, "") : id # strip query params for shrine-url
54
56
  result = File.extname(identifier)[1..-1]
55
57
  result ||= File.extname(original_filename.to_s)[1..-1]
56
58
  result.downcase if result
@@ -89,9 +91,9 @@ class Shrine
89
91
  # # or
90
92
  #
91
93
  # uploaded_file.open { |io| io.read } # the IO is automatically closed
92
- def open(**options)
94
+ def open(**)
93
95
  @io.close if @io
94
- @io = _open(**options)
96
+ @io = _open(**)
95
97
 
96
98
  return @io unless block_given?
97
99
 
@@ -118,9 +120,9 @@ class Shrine
118
120
  # # or
119
121
  #
120
122
  # uploaded_file.download { |tempfile| tempfile.read } # tempfile is deleted
121
- def download(**options)
123
+ def download(**)
122
124
  tempfile = Tempfile.new(["shrine", ".#{extension}"], binmode: true)
123
- stream(tempfile, **options)
125
+ stream(tempfile, **)
124
126
  tempfile.open
125
127
 
126
128
  block_given? ? yield(tempfile) : tempfile
@@ -139,19 +141,19 @@ class Shrine
139
141
  # uploaded_file.stream(StringIO.new)
140
142
  # # or
141
143
  # uploaded_file.stream("/path/to/destination")
142
- def stream(destination, **options)
144
+ def stream(destination, **)
143
145
  if opened?
144
146
  IO.copy_stream(io, destination)
145
147
  io.rewind
146
148
  else
147
- open(**options) { |io| IO.copy_stream(io, destination) }
149
+ open(**) { |io| IO.copy_stream(io, destination) }
148
150
  end
149
151
  end
150
152
 
151
153
  # Part of complying to the IO interface. It delegates to the internally
152
154
  # opened IO object.
153
- def read(*args)
154
- io.read(*args)
155
+ def read(*)
156
+ io.read(*)
155
157
  end
156
158
 
157
159
  # Part of complying to the IO interface. It delegates to the internally
@@ -179,8 +181,8 @@ class Shrine
179
181
  end
180
182
 
181
183
  # Calls `#url` on the storage, forwarding any given URL options.
182
- def url(**options)
183
- storage.url(id, **options)
184
+ def url(**)
185
+ storage.url(id, **)
184
186
  end
185
187
 
186
188
  # Calls `#exists?` on the storage, which checks whether the file exists
@@ -190,8 +192,8 @@ class Shrine
190
192
  end
191
193
 
192
194
  # Uploads a new file to this file's location and returns it.
193
- def replace(io, **options)
194
- uploader.upload(io, **options, location: id)
195
+ def replace(io, **)
196
+ uploader.upload(io, **, location: id)
195
197
  end
196
198
 
197
199
  # Calls `#delete` on the storage, which deletes the file from the
@@ -207,12 +209,12 @@ class Shrine
207
209
 
208
210
  # Returns the data hash in the JSON format. Suitable for storing in a
209
211
  # database column or passing to a background job.
210
- def to_json(*args)
211
- data.to_json(*args)
212
+ def to_json(*)
213
+ data.to_json(*)
212
214
  end
213
215
 
214
216
  # Conform to ActiveSupport's JSON interface.
215
- def as_json(*args)
217
+ def as_json(*)
216
218
  data
217
219
  end
218
220
 
@@ -263,8 +265,8 @@ class Shrine
263
265
  @io ||= _open
264
266
  end
265
267
 
266
- def _open(**options)
267
- storage.open(id, **options)
268
+ def _open(**)
269
+ storage.open(id, **)
268
270
  end
269
271
  end
270
272
 
@@ -7,8 +7,8 @@ class Shrine
7
7
 
8
8
  module VERSION
9
9
  MAJOR = 3
10
- MINOR = 6
11
- TINY = 0
10
+ MINOR = 7
11
+ TINY = 1
12
12
  PRE = nil
13
13
 
14
14
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
data/lib/shrine.rb CHANGED
@@ -68,9 +68,9 @@ class Shrine
68
68
  #
69
69
  # Shrine.plugin MyPlugin
70
70
  # Shrine.plugin :my_plugin
71
- def plugin(plugin, *args, **kwargs, &block)
71
+ def plugin(plugin, ...)
72
72
  plugin = Plugins.load_plugin(plugin) if plugin.is_a?(Symbol)
73
- Plugins.load_dependencies(plugin, self, *args, **kwargs, &block)
73
+ Plugins.load_dependencies(plugin, self, ...)
74
74
  self.include(plugin::InstanceMethods) if defined?(plugin::InstanceMethods)
75
75
  self.extend(plugin::ClassMethods) if defined?(plugin::ClassMethods)
76
76
  self::UploadedFile.include(plugin::FileMethods) if defined?(plugin::FileMethods)
@@ -79,7 +79,7 @@ class Shrine
79
79
  self::Attachment.extend(plugin::AttachmentClassMethods) if defined?(plugin::AttachmentClassMethods)
80
80
  self::Attacher.include(plugin::AttacherMethods) if defined?(plugin::AttacherMethods)
81
81
  self::Attacher.extend(plugin::AttacherClassMethods) if defined?(plugin::AttacherClassMethods)
82
- Plugins.configure(plugin, self, *args, **kwargs, &block)
82
+ Plugins.configure(plugin, self, ...)
83
83
  plugin
84
84
  end
85
85
 
@@ -95,8 +95,8 @@ class Shrine
95
95
  # class Photo
96
96
  # include Shrine::Attachment(:image) # creates a Shrine::Attachment object
97
97
  # end
98
- def Attachment(name, **args)
99
- self::Attachment.new(name, **args)
98
+ def Attachment(name, **)
99
+ self::Attachment.new(name, **)
100
100
  end
101
101
  alias attachment Attachment
102
102
  alias [] Attachment
@@ -104,8 +104,8 @@ class Shrine
104
104
  # Uploads the file to the specified storage. It delegates to `Shrine#upload`.
105
105
  #
106
106
  # Shrine.upload(io, :store) #=> #<Shrine::UploadedFile>
107
- def upload(io, storage, **options)
108
- new(storage).upload(io, **options)
107
+ def upload(io, storage, **)
108
+ new(storage).upload(io, **)
109
109
  end
110
110
 
111
111
  # Instantiates a Shrine::UploadedFile from a hash, and optionally
@@ -201,13 +201,13 @@ class Shrine
201
201
  # uploader.upload(io, metadata: { "foo" => "bar" }) # add metadata
202
202
  # uploader.upload(io, location: "path/to/file") # specify location
203
203
  # uploader.upload(io, upload_options: { acl: "public-read" }) # add upload options
204
- def upload(io, **options)
204
+ def upload(io, **)
205
205
  _enforce_io(io)
206
206
 
207
- metadata = get_metadata(io, **options)
208
- location = get_location(io, **options, metadata: metadata)
207
+ metadata = get_metadata(io, **)
208
+ location = get_location(io, **, metadata:)
209
209
 
210
- _upload(io, **options, location: location, metadata: metadata)
210
+ _upload(io, **, location:, metadata:)
211
211
 
212
212
  self.class::UploadedFile.new(
213
213
  id: location,
@@ -219,13 +219,13 @@ class Shrine
219
219
  # Generates a unique location for the uploaded file, preserving the
220
220
  # file extension. Can be overriden in uploaders for generating custom
221
221
  # location.
222
- def generate_location(io, metadata: {}, **options)
223
- basic_location(io, metadata: metadata)
222
+ def generate_location(io, metadata: {}, **)
223
+ basic_location(io, metadata:)
224
224
  end
225
225
 
226
226
  # Extracts filename, size and MIME type from the file, which is later
227
227
  # accessible through UploadedFile#metadata.
228
- def extract_metadata(io, **options)
228
+ def extract_metadata(io, **)
229
229
  {
230
230
  "filename" => extract_filename(io),
231
231
  "size" => extract_size(io),
@@ -281,11 +281,11 @@ class Shrine
281
281
 
282
282
  # If the IO object is a Shrine::UploadedFile, it simply copies over its
283
283
  # metadata, otherwise it calls #extract_metadata.
284
- def get_metadata(io, metadata: nil, **options)
284
+ def get_metadata(io, metadata: nil, **)
285
285
  if io.is_a?(UploadedFile) && metadata != true
286
286
  result = io.metadata.dup
287
287
  elsif metadata != false
288
- result = extract_metadata(io, **options)
288
+ result = extract_metadata(io, **)
289
289
  else
290
290
  result = {}
291
291
  end
@@ -296,8 +296,8 @@ class Shrine
296
296
 
297
297
  # Retrieves the location for the given IO and context. First it looks
298
298
  # for the `:location` option, otherwise it calls #generate_location.
299
- def get_location(io, location: nil, **options)
300
- location ||= generate_location(io, **options)
299
+ def get_location(io, location: nil, **)
300
+ location ||= generate_location(io, **)
301
301
  location or fail Error, "location generated for #{io.inspect} was nil"
302
302
  end
303
303
 
data/shrine.gemspec CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |gem|
4
4
  gem.name = "shrine"
5
5
  gem.version = Shrine.version
6
6
 
7
- gem.required_ruby_version = ">= 2.3"
7
+ gem.required_ruby_version = ">= 3.2"
8
8
 
9
9
  gem.summary = "Toolkit for file attachments in Ruby applications"
10
10
  gem.description = <<-END
@@ -38,7 +38,7 @@ direct uploads for fully asynchronous user experience.
38
38
 
39
39
  # general testing helpers
40
40
  gem.add_development_dependency "rake", ">= 11.1"
41
- gem.add_development_dependency "minitest", "~> 5.8"
41
+ gem.add_development_dependency "minitest", "~> 6.0"
42
42
  gem.add_development_dependency "mocha", "~> 1.11"
43
43
 
44
44
  # for endpoint plugins
@@ -57,7 +57,7 @@ direct uploads for fully asynchronous user experience.
57
57
 
58
58
  # for store_dimensions plugin
59
59
  gem.add_development_dependency "fastimage"
60
- gem.add_development_dependency "mini_magick", "~> 4.0" unless ENV["CI"]
60
+ gem.add_development_dependency "mini_magick", "~> 5.0" unless ENV["CI"]
61
61
  gem.add_development_dependency "ruby-vips", "~> 2.0" unless ENV["CI"]
62
62
 
63
63
  # for S3 storage
@@ -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.7" ? "~> 7.0" : RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
70
+ gem.add_development_dependency "activesupport", RUBY_ENGINE == "jruby" ? "~> 7.2" : "~> 8.1"
71
71
 
72
72
  # for ORM plugins
73
73
  gem.add_development_dependency "sequel"
74
- gem.add_development_dependency "activerecord", RUBY_ENGINE == "jruby" ? "~> 7.0.0" : RUBY_VERSION >= "2.7" ? "~> 7.0" : RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
75
- gem.add_development_dependency "sqlite3", "~> 1.4" unless RUBY_ENGINE == "jruby"
74
+ gem.add_development_dependency "activerecord", RUBY_ENGINE == "jruby" ? "~> 7.2" : "~> 8.1"
75
+ gem.add_development_dependency "sqlite3", "~> 2.1" unless RUBY_ENGINE == "jruby"
76
76
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-04-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: down
@@ -58,14 +57,14 @@ dependencies:
58
57
  requirements:
59
58
  - - "~>"
60
59
  - !ruby/object:Gem::Version
61
- version: '5.8'
60
+ version: '6.0'
62
61
  type: :development
63
62
  prerelease: false
64
63
  version_requirements: !ruby/object:Gem::Requirement
65
64
  requirements:
66
65
  - - "~>"
67
66
  - !ruby/object:Gem::Version
68
- version: '5.8'
67
+ version: '6.0'
69
68
  - !ruby/object:Gem::Dependency
70
69
  name: mocha
71
70
  requirement: !ruby/object:Gem::Requirement
@@ -218,14 +217,14 @@ dependencies:
218
217
  requirements:
219
218
  - - "~>"
220
219
  - !ruby/object:Gem::Version
221
- version: '4.0'
220
+ version: '5.0'
222
221
  type: :development
223
222
  prerelease: false
224
223
  version_requirements: !ruby/object:Gem::Requirement
225
224
  requirements:
226
225
  - - "~>"
227
226
  - !ruby/object:Gem::Version
228
- version: '4.0'
227
+ version: '5.0'
229
228
  - !ruby/object:Gem::Dependency
230
229
  name: ruby-vips
231
230
  requirement: !ruby/object:Gem::Requirement
@@ -302,14 +301,14 @@ dependencies:
302
301
  requirements:
303
302
  - - "~>"
304
303
  - !ruby/object:Gem::Version
305
- version: '7.0'
304
+ version: '8.1'
306
305
  type: :development
307
306
  prerelease: false
308
307
  version_requirements: !ruby/object:Gem::Requirement
309
308
  requirements:
310
309
  - - "~>"
311
310
  - !ruby/object:Gem::Version
312
- version: '7.0'
311
+ version: '8.1'
313
312
  - !ruby/object:Gem::Dependency
314
313
  name: sequel
315
314
  requirement: !ruby/object:Gem::Requirement
@@ -330,28 +329,28 @@ dependencies:
330
329
  requirements:
331
330
  - - "~>"
332
331
  - !ruby/object:Gem::Version
333
- version: '7.0'
332
+ version: '8.1'
334
333
  type: :development
335
334
  prerelease: false
336
335
  version_requirements: !ruby/object:Gem::Requirement
337
336
  requirements:
338
337
  - - "~>"
339
338
  - !ruby/object:Gem::Version
340
- version: '7.0'
339
+ version: '8.1'
341
340
  - !ruby/object:Gem::Dependency
342
341
  name: sqlite3
343
342
  requirement: !ruby/object:Gem::Requirement
344
343
  requirements:
345
344
  - - "~>"
346
345
  - !ruby/object:Gem::Version
347
- version: '1.4'
346
+ version: '2.1'
348
347
  type: :development
349
348
  prerelease: false
350
349
  version_requirements: !ruby/object:Gem::Requirement
351
350
  requirements:
352
351
  - - "~>"
353
352
  - !ruby/object:Gem::Version
354
- version: '1.4'
353
+ version: '2.1'
355
354
  description: |
356
355
  Shrine is a toolkit for file attachments in Ruby applications. It supports
357
356
  uploading, downloading, processing and deleting IO objects, backed by various
@@ -482,6 +481,8 @@ files:
482
481
  - doc/release_notes/3.4.0.md
483
482
  - doc/release_notes/3.5.0.md
484
483
  - doc/release_notes/3.6.0.md
484
+ - doc/release_notes/3.7.0.md
485
+ - doc/release_notes/3.7.1.md
485
486
  - doc/retrieving_uploads.md
486
487
  - doc/securing_uploads.md
487
488
  - doc/storage/file_system.md
@@ -561,7 +562,6 @@ metadata:
561
562
  documentation_uri: https://shrinerb.com
562
563
  mailing_list_uri: https://discourse.shrinerb.com
563
564
  source_code_uri: https://github.com/shrinerb/shrine
564
- post_install_message:
565
565
  rdoc_options: []
566
566
  require_paths:
567
567
  - lib
@@ -569,15 +569,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
569
569
  requirements:
570
570
  - - ">="
571
571
  - !ruby/object:Gem::Version
572
- version: '2.3'
572
+ version: '3.2'
573
573
  required_rubygems_version: !ruby/object:Gem::Requirement
574
574
  requirements:
575
575
  - - ">="
576
576
  - !ruby/object:Gem::Version
577
577
  version: '0'
578
578
  requirements: []
579
- rubygems_version: 3.5.9
580
- signing_key:
579
+ rubygems_version: 3.6.9
581
580
  specification_version: 4
582
581
  summary: Toolkit for file attachments in Ruby applications
583
582
  test_files: []