shrine 3.1.0 → 3.4.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/README.md +11 -4
- data/doc/advantages.md +4 -4
- data/doc/attacher.md +2 -2
- data/doc/carrierwave.md +24 -12
- data/doc/changing_derivatives.md +1 -1
- data/doc/changing_location.md +6 -5
- data/doc/design.md +134 -85
- data/doc/direct_s3.md +26 -0
- data/doc/external/articles.md +57 -45
- data/doc/external/extensions.md +41 -35
- data/doc/external/misc.md +23 -8
- data/doc/getting_started.md +156 -85
- data/doc/metadata.md +80 -44
- data/doc/multiple_files.md +1 -1
- data/doc/paperclip.md +28 -9
- data/doc/plugins/add_metadata.md +112 -35
- data/doc/plugins/atomic_helpers.md +41 -3
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivatives.md +83 -44
- data/doc/plugins/download_endpoint.md +5 -5
- data/doc/plugins/dynamic_storage.md +1 -1
- data/doc/plugins/entity.md +12 -4
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +9 -0
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +1 -0
- data/doc/plugins/mirroring.md +1 -1
- data/doc/plugins/model.md +8 -3
- data/doc/plugins/persistence.md +10 -1
- data/doc/plugins/remote_url.md +6 -1
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/sequel.md +1 -1
- data/doc/plugins/store_dimensions.md +10 -0
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +1 -1
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +4 -4
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/versions.md +7 -7
- data/doc/processing.md +287 -123
- data/doc/refile.md +9 -9
- data/doc/release_notes/2.8.0.md +1 -1
- data/doc/release_notes/3.0.0.md +1 -1
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/release_notes/3.4.0.md +35 -0
- data/doc/securing_uploads.md +2 -2
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +104 -77
- data/doc/testing.md +12 -2
- data/doc/upgrading_to_3.md +99 -53
- data/lib/shrine.rb +9 -8
- data/lib/shrine/attacher.rb +20 -10
- data/lib/shrine/attachment.rb +2 -2
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/activerecord.rb +3 -3
- data/lib/shrine/plugins/add_metadata.rb +20 -5
- data/lib/shrine/plugins/backgrounding.rb +2 -2
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +13 -8
- data/lib/shrine/plugins/derivatives.rb +59 -30
- data/lib/shrine/plugins/determine_mime_type.rb +5 -3
- data/lib/shrine/plugins/entity.rb +12 -11
- data/lib/shrine/plugins/instrumentation.rb +12 -18
- data/lib/shrine/plugins/mirroring.rb +8 -8
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +16 -4
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_attachment.rb +5 -0
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/store_dimensions.rb +4 -2
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +10 -5
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/memory.rb +5 -3
- data/lib/shrine/storage/s3.rb +117 -38
- data/lib/shrine/version.rb +1 -1
- data/shrine.gemspec +8 -8
- metadata +42 -34
data/lib/shrine/attachment.rb
CHANGED
data/lib/shrine/plugins.rb
CHANGED
@@ -18,6 +18,28 @@ class Shrine
|
|
18
18
|
plugin
|
19
19
|
end
|
20
20
|
|
21
|
+
# Delegate call to the plugin in a way that works across Ruby versions.
|
22
|
+
def self.load_dependencies(plugin, uploader, *args, **kwargs, &block)
|
23
|
+
return unless plugin.respond_to?(:load_dependencies)
|
24
|
+
|
25
|
+
if kwargs.any?
|
26
|
+
plugin.load_dependencies(uploader, *args, **kwargs, &block)
|
27
|
+
else
|
28
|
+
plugin.load_dependencies(uploader, *args, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Delegate call to the plugin in a way that works across Ruby versions.
|
33
|
+
def self.configure(plugin, uploader, *args, **kwargs, &block)
|
34
|
+
return unless plugin.respond_to?(:configure)
|
35
|
+
|
36
|
+
if kwargs.any?
|
37
|
+
plugin.configure(uploader, *args, **kwargs, &block)
|
38
|
+
else
|
39
|
+
plugin.configure(uploader, *args, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
21
43
|
# Register the given plugin with Shrine, so that it can be loaded using
|
22
44
|
# `Shrine.plugin` with a symbol. Should be used by plugin files. Example:
|
23
45
|
#
|
@@ -55,7 +55,7 @@ class Shrine
|
|
55
55
|
# reload the attacher on record reload
|
56
56
|
define_method :reload do |*args|
|
57
57
|
result = super(*args)
|
58
|
-
|
58
|
+
send(:"#{name}_attacher").reload if instance_variable_defined?(:"@#{name}_attacher")
|
59
59
|
result
|
60
60
|
end
|
61
61
|
end
|
@@ -75,8 +75,8 @@ class Shrine
|
|
75
75
|
def activerecord_validate
|
76
76
|
return unless respond_to?(:errors)
|
77
77
|
|
78
|
-
errors.each do |
|
79
|
-
record.errors.add(name,
|
78
|
+
errors.each do |(type, options)|
|
79
|
+
record.errors.add(name, type, **options.to_h)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -9,8 +9,8 @@ class Shrine
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
def add_metadata(name = nil, &block)
|
13
|
-
opts[:add_metadata][:definitions] << [name, block]
|
12
|
+
def add_metadata(name = nil, **options, &block)
|
13
|
+
opts[:add_metadata][:definitions] << [name, options, block]
|
14
14
|
|
15
15
|
metadata_method(name) if name
|
16
16
|
end
|
@@ -40,10 +40,12 @@ class Shrine
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def extract_custom_metadata(io, **options)
|
43
|
-
opts[:add_metadata][:definitions].each do |name, block|
|
44
|
-
result = instance_exec(io, options, &block)
|
43
|
+
opts[:add_metadata][:definitions].each do |name, definition_options, block|
|
44
|
+
result = instance_exec(io, **options, &block)
|
45
45
|
|
46
|
-
if
|
46
|
+
if result.nil? && definition_options[:skip_nil]
|
47
|
+
# Do not store this metadata
|
48
|
+
elsif name
|
47
49
|
options[:metadata].merge! name.to_s => result
|
48
50
|
else
|
49
51
|
options[:metadata].merge! result.transform_keys(&:to_s) if result
|
@@ -54,6 +56,19 @@ class Shrine
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
59
|
+
|
60
|
+
module AttacherMethods
|
61
|
+
def add_metadata(new_metadata, &block)
|
62
|
+
file!.add_metadata(new_metadata, &block)
|
63
|
+
set(file) # trigger model write
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module FileMethods
|
68
|
+
def add_metadata(new_metadata, &block)
|
69
|
+
@metadata = @metadata.merge(new_metadata, &block)
|
70
|
+
end
|
71
|
+
end
|
57
72
|
end
|
58
73
|
|
59
74
|
register_plugin(:add_metadata, AddMetadata)
|
@@ -392,6 +392,7 @@ class Shrine
|
|
392
392
|
options[:type] = request.params["type"] if request.params["type"]
|
393
393
|
options[:disposition] = request.params["disposition"] if request.params["disposition"]
|
394
394
|
options[:filename] = request.params["filename"] if request.params["filename"]
|
395
|
+
options[:version] = request.params["version"] if request.params["version"]
|
395
396
|
options[:expires_in] = expires_in(request) if request.params["expires_at"]
|
396
397
|
|
397
398
|
derivation = uploaded_file.derivation(name, *args, **options)
|
@@ -475,9 +476,9 @@ class Shrine
|
|
475
476
|
file_response(derivative, env)
|
476
477
|
end
|
477
478
|
|
478
|
-
# Generates a Rack response triple from a local file
|
479
|
-
#
|
480
|
-
#
|
479
|
+
# Generates a Rack response triple from a local file. Fills in
|
480
|
+
# `Content-Type` and `Content-Disposition` response headers from derivation
|
481
|
+
# options and file extension of the derivation result.
|
481
482
|
def file_response(file, env)
|
482
483
|
response = rack_file_response(file.path, env)
|
483
484
|
|
@@ -511,7 +512,7 @@ class Shrine
|
|
511
512
|
end
|
512
513
|
|
513
514
|
if upload_redirect
|
514
|
-
redirect_url = uploaded_file.url(upload_redirect_url_options)
|
515
|
+
redirect_url = uploaded_file.url(**upload_redirect_url_options)
|
515
516
|
|
516
517
|
[302, { "Location" => redirect_url }, []]
|
517
518
|
else
|
@@ -528,10 +529,14 @@ class Shrine
|
|
528
529
|
end
|
529
530
|
end
|
530
531
|
|
531
|
-
# We call `Rack::
|
532
|
+
# We call `Rack::Files` with no default `Content-Type`, and make sure we
|
532
533
|
# stay compatible with both Rack 2.x and 1.6.x.
|
533
534
|
def rack_file_response(path, env)
|
534
|
-
|
535
|
+
if Rack.release >= "2.1"
|
536
|
+
server = Rack::Files.new("", {}, nil)
|
537
|
+
else
|
538
|
+
server = Rack::File.new("", {}, nil)
|
539
|
+
end
|
535
540
|
|
536
541
|
if Rack.release > "2"
|
537
542
|
server.serving(Rack::Request.new(env), path)
|
@@ -598,7 +603,7 @@ class Shrine
|
|
598
603
|
def instrument_derivation(&block)
|
599
604
|
return yield unless shrine_class.respond_to?(:instrument)
|
600
605
|
|
601
|
-
shrine_class.instrument(:derivation, derivation: derivation, &block)
|
606
|
+
shrine_class.instrument(:derivation, { derivation: derivation }, &block)
|
602
607
|
end
|
603
608
|
|
604
609
|
# Massages the derivation result, ensuring it's opened in binary mode,
|
@@ -734,7 +739,7 @@ class Shrine
|
|
734
739
|
def verify_signature(string, signature)
|
735
740
|
if signature.nil?
|
736
741
|
fail InvalidSignature, "missing \"signature\" param"
|
737
|
-
elsif signature
|
742
|
+
elsif !Rack::Utils.secure_compare(signature, generate_signature(string))
|
738
743
|
fail InvalidSignature, "provided signature does not match the calculated signature"
|
739
744
|
end
|
740
745
|
end
|
@@ -4,8 +4,6 @@ class Shrine
|
|
4
4
|
module Plugins
|
5
5
|
# Documentation can be found on https://shrinerb.com/docs/plugins/derivatives
|
6
6
|
module Derivatives
|
7
|
-
NOOP_PROCESSOR = -> (*) { Hash.new }
|
8
|
-
|
9
7
|
LOG_SUBSCRIBER = -> (event) do
|
10
8
|
Shrine.logger.info "Derivatives (#{event.duration}ms) – #{{
|
11
9
|
processor: event[:processor],
|
@@ -21,7 +19,7 @@ class Shrine
|
|
21
19
|
end
|
22
20
|
|
23
21
|
def self.configure(uploader, log_subscriber: LOG_SUBSCRIBER, **opts)
|
24
|
-
uploader.opts[:derivatives] ||= { processors: {}, storage: proc { store_key } }
|
22
|
+
uploader.opts[:derivatives] ||= { processors: {}, processor_settings: {}, storage: proc { store_key } }
|
25
23
|
uploader.opts[:derivatives].merge!(opts)
|
26
24
|
|
27
25
|
# instrumentation plugin integration
|
@@ -40,8 +38,8 @@ class Shrine
|
|
40
38
|
def define_model_methods(name)
|
41
39
|
super if defined?(super)
|
42
40
|
|
43
|
-
define_method(:"#{name}_derivatives!") do |*args|
|
44
|
-
send(:"#{name}_attacher").create_derivatives(*args)
|
41
|
+
define_method(:"#{name}_derivatives!") do |*args, **options|
|
42
|
+
send(:"#{name}_attacher").create_derivatives(*args, **options)
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -52,20 +50,37 @@ class Shrine
|
|
52
50
|
# Attacher.derivatives_processor :thumbnails do |original|
|
53
51
|
# # ...
|
54
52
|
# end
|
55
|
-
|
53
|
+
#
|
54
|
+
# By default, Shrine will convert the source IO object into a file
|
55
|
+
# before it's passed to the processor block. You can set `download:
|
56
|
+
# false` to pass the source IO object to the processor block as is.
|
57
|
+
#
|
58
|
+
# Attacher.derivatives_processor :thumbnails, download: false do |original|
|
59
|
+
# # ...
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# This can be useful if you'd like to defer or avoid a possibly
|
63
|
+
# expensive download operation for processor logic that does not
|
64
|
+
# require it.
|
65
|
+
def derivatives_processor(name = :default, download: true, &block)
|
56
66
|
if block
|
57
|
-
shrine_class.
|
67
|
+
shrine_class.derivatives_options[:processors][name.to_sym] = block
|
68
|
+
shrine_class.derivatives_options[:processor_settings][name.to_sym] = { download: download }
|
58
69
|
else
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
fail Error, "derivatives processor #{name.inspect} not registered" unless processor
|
63
|
-
|
64
|
-
processor
|
70
|
+
shrine_class.derivatives_options[:processors].fetch(name.to_sym) do
|
71
|
+
fail Error, "derivatives processor #{name.inspect} not registered" unless name == :default
|
72
|
+
end
|
65
73
|
end
|
66
74
|
end
|
67
75
|
alias derivatives derivatives_processor
|
68
76
|
|
77
|
+
# Returns settings for the given derivatives processor.
|
78
|
+
#
|
79
|
+
# Attacher.derivatives_processor_settings(:thumbnails) #=> { download: true }
|
80
|
+
def derivatives_processor_settings(name)
|
81
|
+
shrine_class.derivatives_options[:processor_settings][name.to_sym] || {}
|
82
|
+
end
|
83
|
+
|
69
84
|
# Specifies default storage to which derivatives will be uploaded.
|
70
85
|
#
|
71
86
|
# Attacher.derivatives_storage :other_store
|
@@ -79,9 +94,9 @@ class Shrine
|
|
79
94
|
# end
|
80
95
|
def derivatives_storage(storage_key = nil, &block)
|
81
96
|
if storage_key || block
|
82
|
-
shrine_class.
|
97
|
+
shrine_class.derivatives_options[:storage] = storage_key || block
|
83
98
|
else
|
84
|
-
shrine_class.
|
99
|
+
shrine_class.derivatives_options[:storage]
|
85
100
|
end
|
86
101
|
end
|
87
102
|
end
|
@@ -147,6 +162,7 @@ class Shrine
|
|
147
162
|
def promote(**options)
|
148
163
|
super
|
149
164
|
promote_derivatives
|
165
|
+
create_derivatives if create_derivatives_on_promote?
|
150
166
|
end
|
151
167
|
|
152
168
|
# Uploads any cached derivatives to permanent storage.
|
@@ -227,8 +243,6 @@ class Shrine
|
|
227
243
|
# hash[:thumb] #=> #<Shrine::UploadedFile>
|
228
244
|
def upload_derivatives(files, **options)
|
229
245
|
map_derivative(files) do |path, file|
|
230
|
-
path = derivative_path(path)
|
231
|
-
|
232
246
|
upload_derivative(path, file, **options)
|
233
247
|
end
|
234
248
|
end
|
@@ -238,6 +252,7 @@ class Shrine
|
|
238
252
|
# hash = attacher.upload_derivative(:thumb, thumb)
|
239
253
|
# hash[:thumb] #=> #<Shrine::UploadedFile>
|
240
254
|
def upload_derivative(path, file, storage: nil, **options)
|
255
|
+
path = derivative_path(path)
|
241
256
|
storage ||= derivative_storage(path)
|
242
257
|
|
243
258
|
file.open if file.is_a?(Tempfile) # refresh file descriptor
|
@@ -269,8 +284,10 @@ class Shrine
|
|
269
284
|
|
270
285
|
source ||= file!
|
271
286
|
|
272
|
-
|
273
|
-
|
287
|
+
processor_settings = self.class.derivatives_processor_settings(processor_name) || {}
|
288
|
+
|
289
|
+
if processor_settings[:download]
|
290
|
+
shrine_class.with_file(source) do |file|
|
274
291
|
_process_derivatives(processor_name, file, **options)
|
275
292
|
end
|
276
293
|
else
|
@@ -374,7 +391,7 @@ class Shrine
|
|
374
391
|
# attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
|
375
392
|
def set_derivatives(derivatives)
|
376
393
|
self.derivatives = derivatives
|
377
|
-
set file # trigger model
|
394
|
+
set file # trigger model write
|
378
395
|
derivatives
|
379
396
|
end
|
380
397
|
|
@@ -442,7 +459,7 @@ class Shrine
|
|
442
459
|
# attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
|
443
460
|
# attacher.change(file)
|
444
461
|
# attacher.derivatives #=> {}
|
445
|
-
def change(*
|
462
|
+
def change(*)
|
446
463
|
result = super
|
447
464
|
set_derivatives({})
|
448
465
|
result
|
@@ -463,8 +480,8 @@ class Shrine
|
|
463
480
|
# Iterates through nested derivatives and maps results.
|
464
481
|
#
|
465
482
|
# attacher.map_derivative(derivatives) { |path, file| ... }
|
466
|
-
def map_derivative(
|
467
|
-
shrine_class.map_derivative(
|
483
|
+
def map_derivative(derivatives, **options, &block)
|
484
|
+
shrine_class.map_derivative(derivatives, **options, &block)
|
468
485
|
end
|
469
486
|
|
470
487
|
private
|
@@ -473,7 +490,9 @@ class Shrine
|
|
473
490
|
def _process_derivatives(processor_name, source, **options)
|
474
491
|
processor = self.class.derivatives_processor(processor_name)
|
475
492
|
|
476
|
-
|
493
|
+
return {} unless processor
|
494
|
+
|
495
|
+
result = instrument_derivatives(processor_name, source, options) do
|
477
496
|
instance_exec(source, **options, &processor)
|
478
497
|
end
|
479
498
|
|
@@ -485,20 +504,20 @@ class Shrine
|
|
485
504
|
end
|
486
505
|
|
487
506
|
# Sends a `derivatives.shrine` event for instrumentation plugin.
|
488
|
-
def instrument_derivatives(processor_name, processor_options, &block)
|
507
|
+
def instrument_derivatives(processor_name, source, processor_options, &block)
|
489
508
|
return yield unless shrine_class.respond_to?(:instrument)
|
490
509
|
|
491
|
-
shrine_class.instrument(
|
492
|
-
:derivatives,
|
510
|
+
shrine_class.instrument(:derivatives, {
|
493
511
|
processor: processor_name,
|
494
512
|
processor_options: processor_options,
|
495
|
-
|
496
|
-
|
513
|
+
io: source,
|
514
|
+
attacher: self,
|
515
|
+
}, &block)
|
497
516
|
end
|
498
517
|
|
499
518
|
# Returns symbolized array or single key.
|
500
519
|
def derivative_path(path)
|
501
|
-
path = path.map { |key| key.is_a?(String) ? key.to_sym : key }
|
520
|
+
path = Array(path).map { |key| key.is_a?(String) ? key.to_sym : key }
|
502
521
|
path = path.first if path.one?
|
503
522
|
path
|
504
523
|
end
|
@@ -520,6 +539,11 @@ class Shrine
|
|
520
539
|
o2
|
521
540
|
end
|
522
541
|
end
|
542
|
+
|
543
|
+
# Whether to automatically create derivatives on promotion
|
544
|
+
def create_derivatives_on_promote?
|
545
|
+
shrine_class.derivatives_options[:create_on_promote]
|
546
|
+
end
|
523
547
|
end
|
524
548
|
|
525
549
|
module ClassMethods
|
@@ -576,6 +600,11 @@ class Shrine
|
|
576
600
|
yield path, object
|
577
601
|
end
|
578
602
|
end
|
603
|
+
|
604
|
+
# Returns derivatives plugin options.
|
605
|
+
def derivatives_options
|
606
|
+
opts[:derivatives]
|
607
|
+
end
|
579
608
|
end
|
580
609
|
|
581
610
|
module FileMethods
|
@@ -124,6 +124,8 @@ class Shrine
|
|
124
124
|
require "fastimage"
|
125
125
|
|
126
126
|
type = FastImage.type(io)
|
127
|
+
return 'image/svg+xml' if type == :svg
|
128
|
+
|
127
129
|
"image/#{type}" if type
|
128
130
|
end
|
129
131
|
|
@@ -141,7 +143,7 @@ class Shrine
|
|
141
143
|
require "mimemagic"
|
142
144
|
|
143
145
|
mime = MimeMagic.by_magic(io)
|
144
|
-
mime
|
146
|
+
mime&.type
|
145
147
|
end
|
146
148
|
|
147
149
|
def extract_with_marcel(io, options)
|
@@ -158,7 +160,7 @@ class Shrine
|
|
158
160
|
|
159
161
|
if filename = extract_filename(io)
|
160
162
|
mime_type = MIME::Types.of(filename).first
|
161
|
-
mime_type
|
163
|
+
mime_type&.content_type
|
162
164
|
end
|
163
165
|
end
|
164
166
|
|
@@ -167,7 +169,7 @@ class Shrine
|
|
167
169
|
|
168
170
|
if filename = extract_filename(io)
|
169
171
|
info = MiniMime.lookup_by_filename(filename)
|
170
|
-
info
|
172
|
+
info&.content_type
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
@@ -41,27 +41,27 @@ class Shrine
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# Returns the URL to the attached file.
|
44
|
-
define_method :"#{name}_url" do |*args|
|
45
|
-
send(:"#{name}_attacher").url(*args)
|
44
|
+
define_method :"#{name}_url" do |*args, **options|
|
45
|
+
send(:"#{name}_attacher").url(*args, **options)
|
46
46
|
end
|
47
47
|
|
48
48
|
# Returns an attacher instance.
|
49
49
|
define_method :"#{name}_attacher" do |**options|
|
50
|
-
attachment.send(:attacher, self, options)
|
50
|
+
attachment.send(:attacher, self, **options)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
# Returns the class attacher instance with loaded entity. It's not
|
55
55
|
# memoized because the entity object could be frozen.
|
56
|
-
def attacher(record, options)
|
57
|
-
attacher = class_attacher(options)
|
56
|
+
def attacher(record, **options)
|
57
|
+
attacher = class_attacher(**options)
|
58
58
|
attacher.load_entity(record, @name)
|
59
59
|
attacher
|
60
60
|
end
|
61
61
|
|
62
62
|
# Creates an instance of the corresponding attacher class with set
|
63
63
|
# name.
|
64
|
-
def class_attacher(options)
|
64
|
+
def class_attacher(**options)
|
65
65
|
attacher = shrine_class::Attacher.new(**@options, **options)
|
66
66
|
attacher.instance_variable_set(:@name, @name)
|
67
67
|
attacher
|
@@ -112,9 +112,15 @@ class Shrine
|
|
112
112
|
# attacher.file #=> #<Shrine::UploadedFile>
|
113
113
|
def reload
|
114
114
|
read
|
115
|
+
@previous = nil
|
115
116
|
self
|
116
117
|
end
|
117
118
|
|
119
|
+
# Loads attachment from the entity attribute.
|
120
|
+
def read
|
121
|
+
load_column(read_attribute)
|
122
|
+
end
|
123
|
+
|
118
124
|
# Returns a hash with entity attribute name and column data.
|
119
125
|
#
|
120
126
|
# attacher.column_values
|
@@ -134,11 +140,6 @@ class Shrine
|
|
134
140
|
|
135
141
|
private
|
136
142
|
|
137
|
-
# Loads attachment from the entity attribute.
|
138
|
-
def read
|
139
|
-
load_column(read_attribute)
|
140
|
-
end
|
141
|
-
|
142
143
|
# Reads value from the entity attribute.
|
143
144
|
def read_attribute
|
144
145
|
record.public_send(attribute)
|