shrine 3.1.0 → 3.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +3 -3
- data/doc/advantages.md +3 -3
- data/doc/carrierwave.md +17 -8
- data/doc/design.md +134 -85
- data/doc/external/articles.md +1 -0
- data/doc/external/extensions.md +38 -35
- data/doc/getting_started.md +135 -79
- data/doc/metadata.md +79 -43
- data/doc/paperclip.md +13 -4
- data/doc/plugins/add_metadata.md +92 -35
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/default_url.md +3 -0
- data/doc/plugins/derivatives.md +35 -27
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/url_options.md +2 -2
- data/doc/plugins/validation.md +5 -4
- data/doc/processing.md +286 -121
- data/doc/refile.md +9 -9
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/securing_uploads.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +102 -81
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +94 -32
- data/lib/shrine.rb +3 -2
- data/lib/shrine/attacher.rb +14 -9
- data/lib/shrine/plugins/add_metadata.rb +13 -0
- data/lib/shrine/plugins/derivatives.rb +8 -7
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/model.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/validation.rb +8 -6
- data/lib/shrine/storage/s3.rb +34 -28
- data/lib/shrine/version.rb +1 -1
- metadata +7 -3
@@ -9,18 +9,23 @@ class Shrine
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module AttacherMethods
|
12
|
-
def
|
12
|
+
def validate(*)
|
13
13
|
super
|
14
14
|
ensure
|
15
|
-
|
15
|
+
deassign if errors.any?
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def
|
20
|
+
def deassign
|
21
21
|
destroy
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
if changed?
|
24
|
+
load_data @previous.data
|
25
|
+
@previous = nil
|
26
|
+
else
|
27
|
+
load_data nil
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shrine
|
4
|
+
module Plugins
|
5
|
+
# Documentation can be found on https://shrinerb.com/docs/plugins/type_predicates
|
6
|
+
module TypePredicates
|
7
|
+
def self.configure(uploader, methods: [], **opts)
|
8
|
+
uploader.opts[:type_predicates] ||= { mime: :mini_mime }
|
9
|
+
uploader.opts[:type_predicates].merge!(opts)
|
10
|
+
|
11
|
+
methods.each do |name|
|
12
|
+
uploader::UploadedFile.send(:define_method, "#{name}?") { type?(name) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def type_lookup(extension, database = nil)
|
18
|
+
database ||= opts[:type_predicates][:mime]
|
19
|
+
database = MimeDatabase.new(database) if database.is_a?(Symbol)
|
20
|
+
database.call(extension.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module FileMethods
|
25
|
+
def image?
|
26
|
+
general_type?("image")
|
27
|
+
end
|
28
|
+
|
29
|
+
def video?
|
30
|
+
general_type?("video")
|
31
|
+
end
|
32
|
+
|
33
|
+
def audio?
|
34
|
+
general_type?("audio")
|
35
|
+
end
|
36
|
+
|
37
|
+
def text?
|
38
|
+
general_type?("text")
|
39
|
+
end
|
40
|
+
|
41
|
+
def type?(type)
|
42
|
+
matching_mime_type = shrine_class.type_lookup(type)
|
43
|
+
|
44
|
+
fail Error, "type #{type.inspect} is not recognized by the MIME library" unless matching_mime_type
|
45
|
+
|
46
|
+
mime_type! == matching_mime_type
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def general_type?(type)
|
52
|
+
mime_type!.start_with?(type)
|
53
|
+
end
|
54
|
+
|
55
|
+
def mime_type!
|
56
|
+
mime_type or fail Error, "mime_type metadata value is missing"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class MimeDatabase
|
61
|
+
SUPPORTED_TOOLS = %i[mini_mime mime_types mimemagic marcel rack_mime]
|
62
|
+
|
63
|
+
def initialize(tool)
|
64
|
+
raise Error, "unknown type database #{tool.inspect}, supported databases are: #{SUPPORTED_TOOLS.join(",")}" unless SUPPORTED_TOOLS.include?(tool)
|
65
|
+
|
66
|
+
@tool = tool
|
67
|
+
end
|
68
|
+
|
69
|
+
def call(extension)
|
70
|
+
send(:"lookup_with_#{@tool}", extension)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def lookup_with_mini_mime(extension)
|
76
|
+
require "mini_mime"
|
77
|
+
|
78
|
+
info = MiniMime.lookup_by_extension(extension)
|
79
|
+
info&.content_type
|
80
|
+
end
|
81
|
+
|
82
|
+
def lookup_with_mime_types(extension)
|
83
|
+
require "mime/types"
|
84
|
+
|
85
|
+
mime_type = MIME::Types.of(".#{extension}").first
|
86
|
+
mime_type&.content_type
|
87
|
+
end
|
88
|
+
|
89
|
+
def lookup_with_mimemagic(extension)
|
90
|
+
require "mimemagic"
|
91
|
+
|
92
|
+
magic = MimeMagic.by_extension(".#{extension}")
|
93
|
+
magic&.type
|
94
|
+
end
|
95
|
+
|
96
|
+
def lookup_with_marcel(extension)
|
97
|
+
require "marcel"
|
98
|
+
|
99
|
+
type = Marcel::MimeType.for(extension: ".#{extension}")
|
100
|
+
type unless type == "application/octet-stream"
|
101
|
+
end
|
102
|
+
|
103
|
+
def lookup_with_rack_mime(extension)
|
104
|
+
require "rack/mime"
|
105
|
+
|
106
|
+
Rack::Mime.mime_type(".#{extension}", nil)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
register_plugin(:type_predicates, TypePredicates)
|
112
|
+
end
|
113
|
+
end
|
@@ -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
|
data/lib/shrine/storage/s3.rb
CHANGED
@@ -179,25 +179,7 @@ class Shrine
|
|
179
179
|
options.merge!(@upload_options)
|
180
180
|
options.merge!(presign_options)
|
181
181
|
|
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
|
182
|
+
send(:"presign_#{method}", id, options)
|
201
183
|
end
|
202
184
|
|
203
185
|
# Deletes the file from the storage.
|
@@ -235,6 +217,17 @@ class Shrine
|
|
235
217
|
|
236
218
|
private
|
237
219
|
|
220
|
+
# Uploads the file to S3. Uses multipart upload for large files.
|
221
|
+
def put(io, id, **options)
|
222
|
+
if io.respond_to?(:size) && io.size && io.size <= @multipart_threshold[:upload]
|
223
|
+
object(id).put(body: io, **options)
|
224
|
+
else # multipart upload
|
225
|
+
object(id).upload_stream(part_size: part_size(io), **options) do |write_stream|
|
226
|
+
IO.copy_stream(io, write_stream)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
238
231
|
# Copies an existing S3 object to a new location. Uses multipart copy for
|
239
232
|
# large files.
|
240
233
|
def copy(io, id, **copy_options)
|
@@ -250,15 +243,28 @@ class Shrine
|
|
250
243
|
object(id).copy_from(io.storage.object(io.id), **options)
|
251
244
|
end
|
252
245
|
|
253
|
-
#
|
254
|
-
def
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
246
|
+
# Generates parameters for a POST upload request.
|
247
|
+
def presign_post(id, options)
|
248
|
+
presigned_post = object(id).presigned_post(options)
|
249
|
+
|
250
|
+
{ method: :post, url: presigned_post.url, fields: presigned_post.fields }
|
251
|
+
end
|
252
|
+
|
253
|
+
# Generates parameters for a PUT upload request.
|
254
|
+
def presign_put(id, options)
|
255
|
+
url = object(id).presigned_url(:put, options)
|
256
|
+
|
257
|
+
# When any of these options are specified, the corresponding request
|
258
|
+
# headers must be included in the upload request.
|
259
|
+
headers = {}
|
260
|
+
headers["Content-Length"] = options[:content_length] if options[:content_length]
|
261
|
+
headers["Content-Type"] = options[:content_type] if options[:content_type]
|
262
|
+
headers["Content-Disposition"] = options[:content_disposition] if options[:content_disposition]
|
263
|
+
headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
|
264
|
+
headers["Content-Language"] = options[:content_language] if options[:content_language]
|
265
|
+
headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
|
266
|
+
|
267
|
+
{ method: :put, url: url, headers: headers }
|
262
268
|
end
|
263
269
|
|
264
270
|
# Determins the part size that should be used when uploading the given IO
|
data/lib/shrine/version.rb
CHANGED
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
|
+
version: 3.2.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: 2019-
|
11
|
+
date: 2019-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: down
|
@@ -424,6 +424,7 @@ files:
|
|
424
424
|
- doc/plugins/signature.md
|
425
425
|
- doc/plugins/store_dimensions.md
|
426
426
|
- doc/plugins/tempfile.md
|
427
|
+
- doc/plugins/type_predicates.md
|
427
428
|
- doc/plugins/upload_endpoint.md
|
428
429
|
- doc/plugins/upload_options.md
|
429
430
|
- doc/plugins/url_options.md
|
@@ -468,9 +469,11 @@ files:
|
|
468
469
|
- doc/release_notes/3.0.0.md
|
469
470
|
- doc/release_notes/3.0.1.md
|
470
471
|
- doc/release_notes/3.1.0.md
|
472
|
+
- doc/release_notes/3.2.0.md
|
471
473
|
- doc/retrieving_uploads.md
|
472
474
|
- doc/securing_uploads.md
|
473
475
|
- doc/storage/file_system.md
|
476
|
+
- doc/storage/memory.md
|
474
477
|
- doc/storage/s3.md
|
475
478
|
- doc/testing.md
|
476
479
|
- doc/upgrading_to_3.md
|
@@ -523,6 +526,7 @@ files:
|
|
523
526
|
- lib/shrine/plugins/signature.rb
|
524
527
|
- lib/shrine/plugins/store_dimensions.rb
|
525
528
|
- lib/shrine/plugins/tempfile.rb
|
529
|
+
- lib/shrine/plugins/type_predicates.rb
|
526
530
|
- lib/shrine/plugins/upload_endpoint.rb
|
527
531
|
- lib/shrine/plugins/upload_options.rb
|
528
532
|
- lib/shrine/plugins/url_options.rb
|
@@ -560,7 +564,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
560
564
|
- !ruby/object:Gem::Version
|
561
565
|
version: '0'
|
562
566
|
requirements: []
|
563
|
-
rubygems_version: 3.
|
567
|
+
rubygems_version: 3.1.1
|
564
568
|
signing_key:
|
565
569
|
specification_version: 4
|
566
570
|
summary: Toolkit for file attachments in Ruby applications
|