shrine 2.1.1 → 2.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/README.md +214 -248
- data/doc/carrierwave.md +11 -22
- data/doc/changing_location.md +3 -3
- data/doc/creating_storages.md +48 -21
- data/doc/direct_s3.md +37 -29
- data/doc/paperclip.md +7 -9
- data/doc/refile.md +8 -11
- data/doc/regenerating_versions.md +14 -19
- data/lib/shrine.rb +53 -23
- data/lib/shrine/plugins/activerecord.rb +36 -15
- data/lib/shrine/plugins/add_metadata.rb +50 -0
- data/lib/shrine/plugins/backgrounding.rb +22 -13
- data/lib/shrine/plugins/backup.rb +4 -3
- data/lib/shrine/plugins/data_uri.rb +1 -1
- data/lib/shrine/plugins/delete_promoted.rb +1 -1
- data/lib/shrine/plugins/delete_raw.rb +1 -1
- data/lib/shrine/plugins/determine_mime_type.rb +12 -3
- data/lib/shrine/plugins/direct_upload.rb +55 -65
- data/lib/shrine/plugins/download_endpoint.rb +7 -3
- data/lib/shrine/plugins/logging.rb +1 -1
- data/lib/shrine/plugins/moving.rb +6 -5
- data/lib/shrine/plugins/processing.rb +50 -0
- data/lib/shrine/plugins/rack_file.rb +3 -0
- data/lib/shrine/plugins/recache.rb +8 -12
- data/lib/shrine/plugins/remove_invalid.rb +1 -1
- data/lib/shrine/plugins/restore_cached_data.rb +1 -3
- data/lib/shrine/plugins/sequel.rb +40 -19
- data/lib/shrine/plugins/versions.rb +22 -23
- data/lib/shrine/storage/file_system.rb +0 -5
- data/lib/shrine/storage/linter.rb +4 -9
- data/lib/shrine/storage/s3.rb +28 -13
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +3 -2
- metadata +24 -9
@@ -1,25 +1,22 @@
|
|
1
1
|
class Shrine
|
2
2
|
module Plugins
|
3
|
-
# The versions plugin enables your uploader to deal with versions
|
4
|
-
#
|
3
|
+
# The versions plugin enables your uploader to deal with versions, by
|
4
|
+
# allowing you to return a Hash of files when processing.
|
5
|
+
#
|
6
|
+
# plugin :versions
|
7
|
+
#
|
5
8
|
# Here is an example of processing image thumbnails using the
|
6
9
|
# [image_processing] gem:
|
7
10
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# class ImageUploader < Shrine
|
11
|
-
# include ImageProcessing::MiniMagick
|
12
|
-
# plugin :versions
|
11
|
+
# include ImageProcessing::MiniMagick
|
12
|
+
# plugin :processing
|
13
13
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# size_300 = resize_to_limit(size_500, 300, 300)
|
14
|
+
# process(:store) do |io, context|
|
15
|
+
# size_700 = resize_to_limit(io.download, 700, 700)
|
16
|
+
# size_500 = resize_to_limit(size_700, 500, 500)
|
17
|
+
# size_300 = resize_to_limit(size_500, 300, 300)
|
19
18
|
#
|
20
|
-
#
|
21
|
-
# end
|
22
|
-
# end
|
19
|
+
# {large: size_700, medium: size_500, small: size_300}
|
23
20
|
# end
|
24
21
|
#
|
25
22
|
# Note that if you want to keep the original file, you can forward it as is
|
@@ -27,11 +24,9 @@ class Shrine
|
|
27
24
|
# an IO-like object), which might avoid downloading depending on the
|
28
25
|
# storage:
|
29
26
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# {original: io, thumb: thumb}
|
34
|
-
# end
|
27
|
+
# process(:store) do |io, context|
|
28
|
+
# # processing thumbnail
|
29
|
+
# {original: io, thumbnail: thumbnail}
|
35
30
|
# end
|
36
31
|
#
|
37
32
|
# Now when you access the stored attachment through the model, a hash of
|
@@ -89,8 +84,12 @@ class Shrine
|
|
89
84
|
#
|
90
85
|
# user.avatar_url(:medium, download: true)
|
91
86
|
#
|
92
|
-
#
|
93
|
-
#
|
87
|
+
# The `context` will now also include the version name, which you can use
|
88
|
+
# when generating a location or a default URL:
|
89
|
+
#
|
90
|
+
# def generate_location(io, context)
|
91
|
+
# "uploads/#{context[:version]}-#{super}"
|
92
|
+
# end
|
94
93
|
#
|
95
94
|
# plugin :default_url do |context|
|
96
95
|
# "/images/defaults/#{context[:version]}.jpg"
|
@@ -211,7 +210,7 @@ class Shrine
|
|
211
210
|
|
212
211
|
def assign_cached(value)
|
213
212
|
cached_file = uploaded_file(value)
|
214
|
-
warn "Generating versions in the :cache
|
213
|
+
warn "Generating versions in the :cache action is deprecated and will be forbidden in Shrine 3." if cached_file.is_a?(Hash)
|
215
214
|
super(cached_file)
|
216
215
|
end
|
217
216
|
end
|
@@ -142,11 +142,6 @@ class Shrine
|
|
142
142
|
path(id).open("rb", &block)
|
143
143
|
end
|
144
144
|
|
145
|
-
# Returns the contents of the file as a String.
|
146
|
-
def read(id)
|
147
|
-
path(id).binread
|
148
|
-
end
|
149
|
-
|
150
145
|
# Returns true if the file exists on the filesystem.
|
151
146
|
def exists?(id)
|
152
147
|
path(id).exist?
|
@@ -37,7 +37,6 @@ class Shrine
|
|
37
37
|
|
38
38
|
lint_download(id)
|
39
39
|
lint_open(id)
|
40
|
-
lint_read(id)
|
41
40
|
lint_exists(id)
|
42
41
|
lint_url(id)
|
43
42
|
lint_delete(id)
|
@@ -52,8 +51,10 @@ class Shrine
|
|
52
51
|
lint_multi_delete(id)
|
53
52
|
end
|
54
53
|
|
55
|
-
storage.
|
56
|
-
|
54
|
+
if storage.respond_to?(:clear!)
|
55
|
+
storage.upload(io_factory.call, id = "quux")
|
56
|
+
lint_clear(id)
|
57
|
+
end
|
57
58
|
end
|
58
59
|
|
59
60
|
def lint_download(id)
|
@@ -69,12 +70,6 @@ class Shrine
|
|
69
70
|
opened.close
|
70
71
|
end
|
71
72
|
|
72
|
-
def lint_read(id)
|
73
|
-
read = storage.read(id)
|
74
|
-
error :read, "doesn't return a string" if !read.is_a?(String)
|
75
|
-
error :read, "returns an empty string" if read.empty?
|
76
|
-
end
|
77
|
-
|
78
73
|
def lint_exists(id)
|
79
74
|
error :exists?, "returns false for a file that was uploaded" if !storage.exists?(id)
|
80
75
|
end
|
data/lib/shrine/storage/s3.rb
CHANGED
@@ -97,18 +97,23 @@ class Shrine
|
|
97
97
|
# be passed to [`Aws::S3::Object#put`], [`Aws::S3::Object#copy_from`]
|
98
98
|
# and [`Aws::S3::Bucket#presigned_post`].
|
99
99
|
#
|
100
|
+
# :multipart_threshold
|
101
|
+
# : The file size over which the storage will use parallelized
|
102
|
+
# multipart copy/upload. Default is `15*1024*1024` (15MB).
|
103
|
+
#
|
100
104
|
# All other options are forwarded to [`Aws::S3::Client#initialize`].
|
101
105
|
#
|
102
106
|
# [`Aws::S3::Object#put`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#put-instance_method
|
103
107
|
# [`Aws::S3::Object#copy_from`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#copy_from-instance_method
|
104
108
|
# [`Aws::S3::Bucket#presigned_post`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_post-instance_method
|
105
109
|
# [`Aws::S3::Client#initialize`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html#initialize-instance_method
|
106
|
-
def initialize(bucket:, prefix: nil, host: nil, upload_options: {}, **s3_options)
|
110
|
+
def initialize(bucket:, prefix: nil, host: nil, upload_options: {}, multipart_threshold: 15*1024*1024, **s3_options)
|
107
111
|
@prefix = prefix
|
108
112
|
@s3 = Aws::S3::Resource.new(**s3_options)
|
109
113
|
@bucket = @s3.bucket(bucket)
|
110
114
|
@host = host
|
111
115
|
@upload_options = upload_options
|
116
|
+
@multipart_threshold = multipart_threshold
|
112
117
|
end
|
113
118
|
|
114
119
|
# If the file is an UploadedFile from S3, issues a COPY command, otherwise
|
@@ -130,7 +135,11 @@ class Shrine
|
|
130
135
|
|
131
136
|
# Downloads the file from S3, and returns a `Tempfile`.
|
132
137
|
def download(id)
|
133
|
-
|
138
|
+
tempfile = Tempfile.new(["s3", File.extname(id)], binmode: true)
|
139
|
+
(object = object(id)).get(response_target: tempfile.path)
|
140
|
+
tempfile.singleton_class.instance_eval { attr_accessor :content_type }
|
141
|
+
tempfile.content_type = object.content_type
|
142
|
+
tempfile.tap(&:open)
|
134
143
|
end
|
135
144
|
|
136
145
|
# Alias for #download.
|
@@ -138,11 +147,6 @@ class Shrine
|
|
138
147
|
Down.open(url(id), ssl_ca_cert: Aws.config[:ssl_ca_bundle])
|
139
148
|
end
|
140
149
|
|
141
|
-
# Returns the contents of the file as a String.
|
142
|
-
def read(id)
|
143
|
-
object(id).get.body.string
|
144
|
-
end
|
145
|
-
|
146
150
|
# Returns true file exists on S3.
|
147
151
|
def exists?(id)
|
148
152
|
object(id).exists?
|
@@ -199,7 +203,12 @@ class Shrine
|
|
199
203
|
|
200
204
|
# Deletes all files from the storage.
|
201
205
|
def clear!
|
202
|
-
bucket.object_versions(prefix: prefix)
|
206
|
+
objects = bucket.object_versions(prefix: prefix)
|
207
|
+
if objects.respond_to?(:batch_delete!)
|
208
|
+
objects.batch_delete!
|
209
|
+
else
|
210
|
+
objects.delete
|
211
|
+
end
|
203
212
|
end
|
204
213
|
|
205
214
|
# Returns a signature for direct uploads. Internally it calls
|
@@ -239,13 +248,18 @@ class Shrine
|
|
239
248
|
|
240
249
|
# Copies an existing S3 object to a new location.
|
241
250
|
def copy(io, id, **options)
|
242
|
-
options
|
251
|
+
options = {multipart_copy: true, content_length: io.size}.update(options) if multipart?(io)
|
243
252
|
object(id).copy_from(io.storage.object(io.id), **options)
|
244
253
|
end
|
245
254
|
|
246
255
|
# Uploads the file to S3.
|
247
256
|
def put(io, id, **options)
|
248
|
-
|
257
|
+
if io.respond_to?(:path)
|
258
|
+
options = {multipart_threshold: @multipart_threshold}.update(options)
|
259
|
+
object(id).upload_file(io.path, **options)
|
260
|
+
else
|
261
|
+
object(id).put(body: io, **options)
|
262
|
+
end
|
249
263
|
end
|
250
264
|
|
251
265
|
# The file is copyable if it's on S3 and on the same Amazon account.
|
@@ -255,9 +269,10 @@ class Shrine
|
|
255
269
|
io.storage.access_key_id == access_key_id
|
256
270
|
end
|
257
271
|
|
258
|
-
#
|
259
|
-
|
260
|
-
|
272
|
+
# Determines whether multipart upload/copy should be used from
|
273
|
+
# `:multipart_threshold`.
|
274
|
+
def multipart?(io)
|
275
|
+
io.size && io.size >= @multipart_threshold
|
261
276
|
end
|
262
277
|
end
|
263
278
|
end
|
data/lib/shrine/version.rb
CHANGED
data/shrine.gemspec
CHANGED
@@ -25,7 +25,7 @@ column, and tying them to record's lifecycle.
|
|
25
25
|
gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "shrine.gemspec", "doc/*.md"]
|
26
26
|
gem.require_path = "lib"
|
27
27
|
|
28
|
-
gem.add_dependency "down", ">= 2.3.
|
28
|
+
gem.add_dependency "down", ">= 2.3.5"
|
29
29
|
|
30
30
|
gem.add_development_dependency "rake", "~> 11.1"
|
31
31
|
gem.add_development_dependency "minitest", "~> 5.8"
|
@@ -37,10 +37,11 @@ column, and tying them to record's lifecycle.
|
|
37
37
|
gem.add_development_dependency "shrine-memory", ">= 0.2.1"
|
38
38
|
|
39
39
|
gem.add_development_dependency "roda"
|
40
|
+
gem.add_development_dependency "rack", "~> 1.6.4"
|
40
41
|
gem.add_development_dependency "mimemagic"
|
41
42
|
gem.add_development_dependency "mime-types"
|
42
43
|
gem.add_development_dependency "fastimage"
|
43
|
-
gem.add_development_dependency "aws-sdk"
|
44
|
+
gem.add_development_dependency "aws-sdk", "~> 2.1"
|
44
45
|
|
45
46
|
unless RUBY_ENGINE == "jruby" || ENV["CI"]
|
46
47
|
gem.add_development_dependency "ruby-filemagic", "~> 0.7"
|
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: 2.
|
4
|
+
version: 2.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: 2016-07-
|
11
|
+
date: 2016-07-29 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: 2.3.
|
19
|
+
version: 2.3.5
|
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: 2.3.
|
26
|
+
version: 2.3.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rack
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 1.6.4
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 1.6.4
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: mimemagic
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,16 +210,16 @@ dependencies:
|
|
196
210
|
name: aws-sdk
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
198
212
|
requirements:
|
199
|
-
- - "
|
213
|
+
- - "~>"
|
200
214
|
- !ruby/object:Gem::Version
|
201
|
-
version: '
|
215
|
+
version: '2.1'
|
202
216
|
type: :development
|
203
217
|
prerelease: false
|
204
218
|
version_requirements: !ruby/object:Gem::Requirement
|
205
219
|
requirements:
|
206
|
-
- - "
|
220
|
+
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
|
-
version: '
|
222
|
+
version: '2.1'
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: ruby-filemagic
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -291,6 +305,7 @@ files:
|
|
291
305
|
- doc/securing_uploads.md
|
292
306
|
- lib/shrine.rb
|
293
307
|
- lib/shrine/plugins/activerecord.rb
|
308
|
+
- lib/shrine/plugins/add_metadata.rb
|
294
309
|
- lib/shrine/plugins/background_helpers.rb
|
295
310
|
- lib/shrine/plugins/backgrounding.rb
|
296
311
|
- lib/shrine/plugins/backup.rb
|
@@ -316,6 +331,7 @@ files:
|
|
316
331
|
- lib/shrine/plugins/parallelize.rb
|
317
332
|
- lib/shrine/plugins/parsed_json.rb
|
318
333
|
- lib/shrine/plugins/pretty_location.rb
|
334
|
+
- lib/shrine/plugins/processing.rb
|
319
335
|
- lib/shrine/plugins/rack_file.rb
|
320
336
|
- lib/shrine/plugins/recache.rb
|
321
337
|
- lib/shrine/plugins/remote_url.rb
|
@@ -357,4 +373,3 @@ signing_key:
|
|
357
373
|
specification_version: 4
|
358
374
|
summary: Toolkit for handling file uploads in Ruby
|
359
375
|
test_files: []
|
360
|
-
has_rdoc:
|