shrine 2.3.1 → 2.4.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 +212 -89
- data/doc/attacher.md +227 -0
- data/doc/design.md +5 -19
- data/doc/paperclip.md +2 -1
- data/doc/testing.md +266 -0
- data/lib/shrine.rb +220 -168
- data/lib/shrine/plugins/activerecord.rb +23 -14
- data/lib/shrine/plugins/backgrounding.rb +3 -3
- data/lib/shrine/plugins/cached_attachment_data.rb +6 -5
- data/lib/shrine/plugins/copy.rb +10 -9
- data/lib/shrine/plugins/data_uri.rb +5 -0
- data/lib/shrine/plugins/default_url_options.rb +17 -4
- data/lib/shrine/plugins/direct_upload.rb +6 -11
- data/lib/shrine/plugins/download_endpoint.rb +8 -24
- data/lib/shrine/plugins/multi_delete.rb +1 -1
- data/lib/shrine/plugins/processing.rb +8 -0
- data/lib/shrine/plugins/remote_url.rb +5 -0
- data/lib/shrine/plugins/remove_attachment.rb +3 -10
- data/lib/shrine/plugins/sequel.rb +28 -25
- data/lib/shrine/plugins/versions.rb +12 -1
- data/lib/shrine/storage/file_system.rb +16 -14
- data/lib/shrine/storage/linter.rb +6 -0
- data/lib/shrine/storage/s3.rb +51 -25
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +2 -2
- metadata +8 -7
- data/lib/shrine/plugins/concatenation.rb +0 -73
@@ -211,9 +211,20 @@ class Shrine
|
|
211
211
|
|
212
212
|
def assign_cached(value)
|
213
213
|
cached_file = uploaded_file(value)
|
214
|
-
warn "
|
214
|
+
warn "Assigning cached hash of files is deprecated for security reasons and will be removed in Shrine 3." if cached_file.is_a?(Hash)
|
215
215
|
super(cached_file)
|
216
216
|
end
|
217
|
+
|
218
|
+
# Converts the Hash of UploadedFile objects into a Hash of data.
|
219
|
+
def convert_to_data(value)
|
220
|
+
if value.is_a?(Hash)
|
221
|
+
value.inject({}) do |hash, (name, uploaded_file)|
|
222
|
+
hash.merge!(name => super(uploaded_file))
|
223
|
+
end
|
224
|
+
else
|
225
|
+
super
|
226
|
+
end
|
227
|
+
end
|
217
228
|
end
|
218
229
|
end
|
219
230
|
|
@@ -25,11 +25,11 @@ class Shrine
|
|
25
25
|
# ## Host
|
26
26
|
#
|
27
27
|
# It's generally a good idea to serve your files via a CDN, so an
|
28
|
-
# additional `:host` option can be provided
|
28
|
+
# additional `:host` option can be provided to `#url`:
|
29
29
|
#
|
30
|
-
# storage = Shrine::Storage::FileSystem.new("public",
|
31
|
-
#
|
32
|
-
#
|
30
|
+
# storage = Shrine::Storage::FileSystem.new("public", prefix: "uploads")
|
31
|
+
# storage.url("image.jpg", host: "http://abc123.cloudfront.net")
|
32
|
+
# #=> "http://abc123.cloudfront.net/uploads/image.jpg"
|
33
33
|
#
|
34
34
|
# If you're not using a CDN, it's recommended that you still set `:host` to
|
35
35
|
# your application's domain (at least in production).
|
@@ -37,8 +37,9 @@ class Shrine
|
|
37
37
|
# The `:host` option can also be used wihout `:prefix`, and is
|
38
38
|
# useful if you for example have files located on another server:
|
39
39
|
#
|
40
|
-
# storage = Shrine::Storage::FileSystem.new("files"
|
41
|
-
# storage.url("image.jpg"
|
40
|
+
# storage = Shrine::Storage::FileSystem.new("/opt/files")
|
41
|
+
# storage.url("image.jpg", host: "http://943.23.43.1")
|
42
|
+
# #=> "http://943.23.43.1/opt/files/image.jpg"
|
42
43
|
#
|
43
44
|
# ## Clearing cache
|
44
45
|
#
|
@@ -80,10 +81,6 @@ class Shrine
|
|
80
81
|
# : The directory relative to `directory` to which files will be stored,
|
81
82
|
# and it is included in the URL.
|
82
83
|
#
|
83
|
-
# :host
|
84
|
-
# : URLs will by default be relative if `:prefix` is set, and you
|
85
|
-
# can use this option to set a CDN host (e.g. `//abc123.cloudfront.net`).
|
86
|
-
#
|
87
84
|
# :permissions
|
88
85
|
# : The UNIX permissions applied to created files. Can be set to `nil`,
|
89
86
|
# in which case the default permissions will be applied. Defaults to
|
@@ -99,6 +96,8 @@ class Shrine
|
|
99
96
|
# deleted, but if it happens that it causes too much load on the
|
100
97
|
# filesystem, you can set this option to `false`.
|
101
98
|
def initialize(directory, prefix: nil, host: nil, clean: true, permissions: 0644, directory_permissions: 0755)
|
99
|
+
warn "The :host option to Shrine::Storage::FileSystem#initialize is deprecated and will be removed in Shrine 3. Pass :host to FileSystem#url instead, you can also use default_url_options plugin." if host
|
100
|
+
|
102
101
|
if prefix
|
103
102
|
@prefix = Pathname(relative(prefix))
|
104
103
|
@directory = Pathname(directory).join(@prefix)
|
@@ -162,12 +161,15 @@ class Shrine
|
|
162
161
|
def delete(id)
|
163
162
|
path(id).delete
|
164
163
|
clean(id) if clean?
|
164
|
+
rescue Errno::ENOENT
|
165
165
|
end
|
166
166
|
|
167
|
-
# If #prefix is present, returns
|
168
|
-
#
|
169
|
-
#
|
170
|
-
|
167
|
+
# If #prefix is not present, returns a path composed of #directory and
|
168
|
+
# the given `id`. If #prefix is present, it excludes the #directory part
|
169
|
+
# from the returned path (e.g. #directory can be set to "public" folder).
|
170
|
+
# Both cases accept a `:host` value which will be prefixed to the
|
171
|
+
# generated path.
|
172
|
+
def url(id, host: self.host, **options)
|
171
173
|
path = (prefix ? relative_path(id) : path(id)).to_s
|
172
174
|
host ? host + path : path
|
173
175
|
end
|
@@ -3,6 +3,7 @@ require "shrine"
|
|
3
3
|
require "forwardable"
|
4
4
|
require "stringio"
|
5
5
|
require "tempfile"
|
6
|
+
require "securerandom"
|
6
7
|
|
7
8
|
class Shrine
|
8
9
|
# Error which is thrown when Storage::Linter fails.
|
@@ -83,6 +84,11 @@ class Shrine
|
|
83
84
|
def lint_delete(id)
|
84
85
|
storage.delete(id)
|
85
86
|
error :delete, "file still #exists? after deleting" if storage.exists?(id)
|
87
|
+
begin
|
88
|
+
storage.delete(SecureRandom.hex)
|
89
|
+
rescue => exception
|
90
|
+
error :delete, "shouldn't fail if the file doesn't exist, but raised #{exception.class}"
|
91
|
+
end
|
86
92
|
end
|
87
93
|
|
88
94
|
def lint_move(uploaded_file, id)
|
data/lib/shrine/storage/s3.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "aws-sdk"
|
2
2
|
require "down"
|
3
3
|
require "uri"
|
4
|
+
require "cgi/util"
|
4
5
|
|
5
6
|
class Shrine
|
6
7
|
module Storage
|
@@ -32,10 +33,7 @@ class Shrine
|
|
32
33
|
# Sometimes you'll want to add additional upload options to all S3 uploads.
|
33
34
|
# You can do that by passing the `:upload` option:
|
34
35
|
#
|
35
|
-
# Shrine::Storage::S3.new(
|
36
|
-
# upload_options: {acl: "public-read", cache_control: "public, max-age=3600"},
|
37
|
-
# **s3_options
|
38
|
-
# )
|
36
|
+
# Shrine::Storage::S3.new(upload_options: {acl: "public-read"}, **s3_options)
|
39
37
|
#
|
40
38
|
# These options will be passed to aws-sdk's methods for [uploading],
|
41
39
|
# [copying] and [presigning].
|
@@ -53,28 +51,40 @@ class Shrine
|
|
53
51
|
# end
|
54
52
|
# end
|
55
53
|
#
|
56
|
-
# Note that
|
57
|
-
#
|
54
|
+
# Note that, unlike the `:upload_options` storage option, the
|
55
|
+
# `upload_options` plugin won't forward the given options for generating
|
56
|
+
# presigns, since presigns are generated using the storage directly.
|
58
57
|
#
|
59
58
|
# ## URL options
|
60
59
|
#
|
61
60
|
# This storage supports various URL options that will be forwarded from
|
62
61
|
# uploaded file.
|
63
62
|
#
|
64
|
-
#
|
65
|
-
#
|
63
|
+
# s3.url(public: true) # public URL without signed parameters
|
64
|
+
# s3.url(download: true) # forced download URL
|
66
65
|
#
|
67
66
|
# All other options are forwarded to the [aws-sdk] gem:
|
68
67
|
#
|
69
|
-
#
|
70
|
-
#
|
68
|
+
# s3.url(expires_in: 15)
|
69
|
+
# s3.url(virtual_host: true)
|
71
70
|
#
|
72
71
|
# ## CDN
|
73
72
|
#
|
74
73
|
# If you're using a CDN with S3 like Amazon CloudFront, you can specify
|
75
|
-
# the `:host` option to
|
74
|
+
# the `:host` option to `#url`:
|
75
|
+
#
|
76
|
+
# s3 = Shrine::Storage::S3.new(**s3_options)
|
77
|
+
# s3.url("image.jpg", host: "http://abc123.cloudfront.net")
|
78
|
+
# #=> "http://abc123.cloudfront.net/image.jpg"
|
79
|
+
#
|
80
|
+
# ## Accelerate endpoint
|
81
|
+
#
|
82
|
+
# To use Amazon S3's [Transfer Acceleration] feature, you can change the
|
83
|
+
# `:endpoint` of the underlying client to the accelerate endpoint, and this
|
84
|
+
# will be applied both to regular and presigned uploads, as well as
|
85
|
+
# download URLs.
|
76
86
|
#
|
77
|
-
# Shrine::Storage::S3.new(
|
87
|
+
# Shrine::Storage::S3.new(endpoint: "https://s3-accelerate.amazonaws.com")
|
78
88
|
#
|
79
89
|
# ## Presigns
|
80
90
|
#
|
@@ -108,6 +118,7 @@ class Shrine
|
|
108
118
|
# [copying]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#copy_from-instance_method
|
109
119
|
# [presigning]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_post-instance_method
|
110
120
|
# [aws-sdk]: https://github.com/aws/aws-sdk-ruby
|
121
|
+
# [Transfer Acceleration]: http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
111
122
|
class S3
|
112
123
|
attr_reader :s3, :bucket, :prefix, :host, :upload_options
|
113
124
|
|
@@ -122,10 +133,6 @@ class Shrine
|
|
122
133
|
# :prefix
|
123
134
|
# : "Folder" name inside the bucket to store files into.
|
124
135
|
#
|
125
|
-
# :host
|
126
|
-
# : This option is used for setting CDNs, e.g. it can be set to
|
127
|
-
# `//abc123.cloudfront.net`.
|
128
|
-
#
|
129
136
|
# :upload_options
|
130
137
|
# : Additional options that will be used for uploading files, they will
|
131
138
|
# be passed to [`Aws::S3::Object#put`], [`Aws::S3::Object#copy_from`]
|
@@ -142,6 +149,8 @@ class Shrine
|
|
142
149
|
# [`Aws::S3::Bucket#presigned_post`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_post-instance_method
|
143
150
|
# [`Aws::S3::Client#initialize`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html#initialize-instance_method
|
144
151
|
def initialize(bucket:, prefix: nil, host: nil, upload_options: {}, multipart_threshold: 15*1024*1024, **s3_options)
|
152
|
+
warn "The :host option to Shrine::Storage::S3#initialize is deprecated and will be removed in Shrine 3. Pass :host to S3#url instead, you can also use default_url_options plugin." if host
|
153
|
+
|
145
154
|
@prefix = prefix
|
146
155
|
@s3 = Aws::S3::Resource.new(**s3_options)
|
147
156
|
@bucket = @s3.bucket(bucket)
|
@@ -156,10 +165,17 @@ class Shrine
|
|
156
165
|
# It assigns the correct "Content-Type" taken from the MIME type, because
|
157
166
|
# by default S3 sets everything to "application/octet-stream".
|
158
167
|
def upload(io, id, shrine_metadata: {}, **upload_options)
|
159
|
-
|
168
|
+
content_type, filename = shrine_metadata.values_at("mime_type", "filename")
|
169
|
+
|
170
|
+
options = {}
|
171
|
+
options[:content_type] = content_type if content_type
|
172
|
+
options[:content_disposition] = "inline; filename=\"#{filename}\"" if filename
|
173
|
+
|
160
174
|
options.update(@upload_options)
|
161
175
|
options.update(upload_options)
|
162
176
|
|
177
|
+
options[:content_disposition] = encode_content_disposition(options[:content_disposition]) if options[:content_disposition]
|
178
|
+
|
163
179
|
if copyable?(io)
|
164
180
|
copy(io, id, **options)
|
165
181
|
else
|
@@ -176,7 +192,7 @@ class Shrine
|
|
176
192
|
tempfile.tap(&:open)
|
177
193
|
end
|
178
194
|
|
179
|
-
#
|
195
|
+
# Returns a `Down::ChunkedIO` object representing the S3 object.
|
180
196
|
def open(id)
|
181
197
|
Down.open(url(id), ssl_ca_cert: Aws.config[:ssl_ca_bundle])
|
182
198
|
end
|
@@ -207,6 +223,11 @@ class Shrine
|
|
207
223
|
# : Creates an unsigned version of the URL (the permissions on the S3
|
208
224
|
# bucket need to be modified to allow public URLs).
|
209
225
|
#
|
226
|
+
# :host
|
227
|
+
# : This option replaces the host part of the returned URL, and is
|
228
|
+
# typically useful for setting CDN hosts (e.g.
|
229
|
+
# `http://abc123.cloudfront.net`)
|
230
|
+
#
|
210
231
|
# :download
|
211
232
|
# : If set to `true`, creates a "forced download" link, which means that
|
212
233
|
# the browser will never display the file and always ask the user to
|
@@ -217,8 +238,9 @@ class Shrine
|
|
217
238
|
#
|
218
239
|
# [`Aws::S3::Object#presigned_url`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method
|
219
240
|
# [`Aws::S3::Object#public_url`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#public_url-instance_method
|
220
|
-
def url(id, download: nil, public: nil, **options)
|
221
|
-
options[:response_content_disposition]
|
241
|
+
def url(id, download: nil, public: nil, host: self.host, **options)
|
242
|
+
options[:response_content_disposition] ||= "attachment" if download
|
243
|
+
options[:response_content_disposition] = encode_content_disposition(options[:response_content_disposition]) if options[:response_content_disposition]
|
222
244
|
|
223
245
|
if public
|
224
246
|
url = object(id).public_url(**options)
|
@@ -238,11 +260,7 @@ class Shrine
|
|
238
260
|
# Deletes all files from the storage.
|
239
261
|
def clear!
|
240
262
|
objects = bucket.object_versions(prefix: prefix)
|
241
|
-
|
242
|
-
objects.batch_delete!
|
243
|
-
else
|
244
|
-
objects.delete
|
245
|
-
end
|
263
|
+
objects.respond_to?(:batch_delete!) ? objects.batch_delete! : objects.delete
|
246
264
|
end
|
247
265
|
|
248
266
|
# Returns a signature for direct uploads. Internally it calls
|
@@ -252,6 +270,8 @@ class Shrine
|
|
252
270
|
# [`Aws::S3::Bucket#presigned_post`]: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Bucket.html#presigned_post-instance_method
|
253
271
|
def presign(id, **options)
|
254
272
|
options = upload_options.merge(options)
|
273
|
+
options[:content_disposition] = encode_content_disposition(options[:content_disposition]) if options[:content_disposition]
|
274
|
+
|
255
275
|
object(id).presigned_post(options)
|
256
276
|
end
|
257
277
|
|
@@ -308,6 +328,12 @@ class Shrine
|
|
308
328
|
def multipart?(io)
|
309
329
|
io.size && io.size >= @multipart_threshold
|
310
330
|
end
|
331
|
+
|
332
|
+
def encode_content_disposition(content_disposition)
|
333
|
+
content_disposition.sub(/(?<=filename=").+(?=")/) do |filename|
|
334
|
+
CGI.escape(filename).sub("+", " ")
|
335
|
+
end
|
336
|
+
end
|
311
337
|
end
|
312
338
|
end
|
313
339
|
end
|
data/lib/shrine/version.rb
CHANGED
data/shrine.gemspec
CHANGED
@@ -26,7 +26,7 @@ direct uploads for fully asynchronous user experience.
|
|
26
26
|
gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "shrine.gemspec", "doc/*.md"]
|
27
27
|
gem.require_path = "lib"
|
28
28
|
|
29
|
-
gem.add_dependency "down", ">= 2.3.
|
29
|
+
gem.add_dependency "down", ">= 2.3.6"
|
30
30
|
|
31
31
|
gem.add_development_dependency "rake", "~> 11.1"
|
32
32
|
gem.add_development_dependency "minitest", "~> 5.8"
|
@@ -35,7 +35,7 @@ direct uploads for fully asynchronous user experience.
|
|
35
35
|
gem.add_development_dependency "webmock"
|
36
36
|
gem.add_development_dependency "rack-test_app"
|
37
37
|
gem.add_development_dependency "dotenv"
|
38
|
-
gem.add_development_dependency "shrine-memory", ">= 0.2.
|
38
|
+
gem.add_development_dependency "shrine-memory", ">= 0.2.2"
|
39
39
|
|
40
40
|
gem.add_development_dependency "roda"
|
41
41
|
gem.add_development_dependency "rack", "~> 1.6.4"
|
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.4.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-
|
11
|
+
date: 2016-10-10 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.6
|
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.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.2.
|
131
|
+
version: 0.2.2
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 0.2.
|
138
|
+
version: 0.2.2
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: roda
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -293,6 +293,7 @@ extra_rdoc_files: []
|
|
293
293
|
files:
|
294
294
|
- LICENSE.txt
|
295
295
|
- README.md
|
296
|
+
- doc/attacher.md
|
296
297
|
- doc/carrierwave.md
|
297
298
|
- doc/changing_location.md
|
298
299
|
- doc/creating_plugins.md
|
@@ -304,6 +305,7 @@ files:
|
|
304
305
|
- doc/refile.md
|
305
306
|
- doc/regenerating_versions.md
|
306
307
|
- doc/securing_uploads.md
|
308
|
+
- doc/testing.md
|
307
309
|
- lib/shrine.rb
|
308
310
|
- lib/shrine/plugins/activerecord.rb
|
309
311
|
- lib/shrine/plugins/add_metadata.rb
|
@@ -311,7 +313,6 @@ files:
|
|
311
313
|
- lib/shrine/plugins/backgrounding.rb
|
312
314
|
- lib/shrine/plugins/backup.rb
|
313
315
|
- lib/shrine/plugins/cached_attachment_data.rb
|
314
|
-
- lib/shrine/plugins/concatenation.rb
|
315
316
|
- lib/shrine/plugins/copy.rb
|
316
317
|
- lib/shrine/plugins/data_uri.rb
|
317
318
|
- lib/shrine/plugins/default_storage.rb
|
@@ -1,73 +0,0 @@
|
|
1
|
-
class Shrine
|
2
|
-
module Plugins
|
3
|
-
# The `concatenation` plugin allows you to assign to the attacher a
|
4
|
-
# cached file which is composed of multiple uploaded parts. The plugin
|
5
|
-
# will then call `#concat` on the storage, which is expected to
|
6
|
-
# concatenate the given parts into a single file. The assigned
|
7
|
-
# attachment will then be a complete cached file.
|
8
|
-
#
|
9
|
-
# plugin :concatenation
|
10
|
-
#
|
11
|
-
# The plugin expects to receive the cached file in the standard JSON
|
12
|
-
# format, with an additional `"parts"` key which is the array of
|
13
|
-
# uploaded parts:
|
14
|
-
#
|
15
|
-
# {
|
16
|
-
# "id": "lsdg94l31.jpg",
|
17
|
-
# "storage": "cache",
|
18
|
-
# "parts": [
|
19
|
-
# {"id": "aaa", "storage": "cache", "metadata": {}},
|
20
|
-
# {"id": "bbb", "storage": "cache", "metadata": {}},
|
21
|
-
# # ...
|
22
|
-
# ],
|
23
|
-
# "metadata": {
|
24
|
-
# # ...
|
25
|
-
# }
|
26
|
-
# }
|
27
|
-
#
|
28
|
-
# The `"metadata"` field of individual parts should contain information
|
29
|
-
# that your storage needs to perform concatenation, refer to the
|
30
|
-
# documentation of your storage.
|
31
|
-
#
|
32
|
-
# You can also pass additional storage-specific concatenation options:
|
33
|
-
#
|
34
|
-
# plugin :concatenation, options: {use_accelerate_endpoint: true}
|
35
|
-
#
|
36
|
-
# plugin :concatenation, options: ->(io, context) do
|
37
|
-
# {use_accelerate_endpoint: true} unless context[:record].guest?
|
38
|
-
# end
|
39
|
-
module Concatenation
|
40
|
-
def self.configure(uploader, opts = {})
|
41
|
-
uploader.opts[:concatenation_options] = opts.fetch(:options, uploader.opts.fetch(:options, {}))
|
42
|
-
end
|
43
|
-
|
44
|
-
module AttacherMethods
|
45
|
-
def assign(value)
|
46
|
-
if value.is_a?(String) && !value.empty?
|
47
|
-
data = JSON.parse(value)
|
48
|
-
|
49
|
-
if data.key?("parts")
|
50
|
-
parts = data["parts"].map { |part_data| uploaded_file(part_data) }
|
51
|
-
location = data["id"]
|
52
|
-
metadata = data["metadata"]
|
53
|
-
|
54
|
-
options = shrine_class.opts[:concatenation_options]
|
55
|
-
options = options.call(uploaded_file(data), context) if options.respond_to?(:call)
|
56
|
-
options ||= {}
|
57
|
-
|
58
|
-
cache.storage.concat(parts, location, shrine_metadata: metadata, **options)
|
59
|
-
|
60
|
-
data.delete("parts")
|
61
|
-
|
62
|
-
assign(data.to_json)
|
63
|
-
else
|
64
|
-
super
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
register_plugin(:concatenation, Concatenation)
|
72
|
-
end
|
73
|
-
end
|