module Shrine::Plugins::Derivatives::AttacherMethods

  1. lib/shrine/plugins/derivatives.rb

Attributes

Public Class methods

new(derivatives: {}, **options)

Adds the ability to accept derivatives.

[show source]
    # File lib/shrine/plugins/derivatives.rb
108 def initialize(derivatives: {}, **options)
109   super(**options)
110 
111   @derivatives       = derivatives
112   @derivatives_mutex = Mutex.new if shrine_class.derivatives_options[:mutex]
113 end

Public Instance methods

add_derivative(name, file, **options)

Uploads a given file and adds it to the derivatives hash.

attacher.derivatives #=>
# {
#   thumb: #<Shrine::UploadedFile>,
# }
attacher.add_derivative(:cropped, cropped)
attacher.derivatives #=>
# {
#   thumb: #<Shrine::UploadedFile>,
#   cropped: #<Shrine::UploadedFile>,
# }
[show source]
    # File lib/shrine/plugins/derivatives.rb
235 def add_derivative(name, file, **options)
236   add_derivatives({ name => file }, **options)
237   derivatives[name]
238 end
add_derivatives(files, **options)

Uploads given hash of files and adds uploaded files to the derivatives hash.

attacher.derivatives #=>
# {
#   thumb: #<Shrine::UploadedFile>,
# }
attacher.add_derivatives({ cropped: cropped })
attacher.derivatives #=>
# {
#   thumb: #<Shrine::UploadedFile>,
#   cropped: #<Shrine::UploadedFile>,
# }
[show source]
    # File lib/shrine/plugins/derivatives.rb
217 def add_derivatives(files, **options)
218   new_derivatives = upload_derivatives(files, **options)
219   merge_derivatives(new_derivatives)
220   new_derivatives
221 end
change(*)

Clears derivatives when attachment changes.

attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
attacher.change(file)
attacher.derivatives #=> {}
[show source]
    # File lib/shrine/plugins/derivatives.rb
462 def change(*)
463   result = super
464   set_derivatives({})
465   result
466 end
create_derivatives(*args, storage: nil, **options)

Calls processor and adds returned derivatives.

Attacher.derivatives_processor :my_processor do |original|
  # ...
end

attacher.create_derivatives(:my_processor)
[show source]
    # File lib/shrine/plugins/derivatives.rb
199 def create_derivatives(*args, storage: nil, **options)
200   files = process_derivatives(*args, **options)
201   add_derivatives(files, storage: storage)
202 end
data()

Adds derivative data into the hash.

attacher.attach(io)
attacher.add_derivatives({ thumb: thumb })
attacher.data
#=>
# {
#   "id" => "...",
#   "storage" => "store",
#   "metadata" => { ... },
#   "derivatives" => {
#     "thumb" => {
#       "id" => "...",
#       "storage" => "store",
#       "metadata" => { ... },
#     }
#   }
# }
[show source]
    # File lib/shrine/plugins/derivatives.rb
416 def data
417   result = super
418 
419   if derivatives.any?
420     result ||= {}
421     result["derivatives"] = map_derivative(derivatives, transform_keys: :to_s) do |_, derivative|
422       derivative.data
423     end
424   end
425 
426   result
427 end
delete_derivatives(derivatives = self.derivatives)

Deletes given hash of uploaded files.

attacher.delete_derivatives({ thumb: uploaded_file })
uploaded_file.exists? #=> false
[show source]
    # File lib/shrine/plugins/derivatives.rb
384 def delete_derivatives(derivatives = self.derivatives)
385   map_derivative(derivatives) { |_, derivative| derivative.delete }
386 end
derivatives=(derivatives)

Sets a hash of derivatives.

attacher.derivatives = { thumb: Shrine.uploaded_file(...) }
attacher.derivatives #=> { thumb: #<Shrine::UploadedFile ...> }
[show source]
    # File lib/shrine/plugins/derivatives.rb
472 def derivatives=(derivatives)
473   unless derivatives.is_a?(Hash)
474     fail ArgumentError, "expected derivatives to be a Hash, got #{derivatives.inspect}"
475   end
476 
477   @derivatives = derivatives
478 end
destroy()

In addition to deleting the main file it also deletes any derivatives.

attacher.add_derivatives({ thumb: thumb })
attacher.derivatives[:thumb].exists? #=> true
attacher.destroy
attacher.derivatives[:thumb].exists? #=> false
[show source]
    # File lib/shrine/plugins/derivatives.rb
187 def destroy
188   super
189   delete_derivatives
190 end
get(*path)

Convenience method for accessing derivatives.

photo.image_derivatives[:thumb] #=> #<Shrine::UploadedFile>
# can be shortened to
photo.image(:thumb) #=> #<Shrine::UploadedFile>
[show source]
    # File lib/shrine/plugins/derivatives.rb
120 def get(*path)
121   return super if path.empty?
122 
123   get_derivatives(*path)
124 end
get_derivatives(*path)

Convenience method for accessing derivatives.

photo.image_derivatives.dig(:thumbnails, :large)
# can be shortened to
photo.image_derivatives(:thumbnails, :large)
[show source]
    # File lib/shrine/plugins/derivatives.rb
131 def get_derivatives(*path)
132   return derivatives if path.empty?
133 
134   path = derivative_path(path)
135 
136   derivatives.dig(*path)
137 end
load_data(data)

Loads derivatives from data generated by Attacher#data.

attacher.load_data({
  "id" => "...",
  "storage" => "store",
  "metadata" => { ... },
  "derivatives" => {
    "thumb" => {
      "id" => "...",
      "storage" => "store",
      "metadata" => { ... },
    }
  }
})
attacher.file        #=> #<Shrine::UploadedFile>
attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
[show source]
    # File lib/shrine/plugins/derivatives.rb
445 def load_data(data)
446   data ||= {}
447   data   = data.dup
448 
449   derivatives_data = data.delete("derivatives") || data.delete(:derivatives) || {}
450   @derivatives     = shrine_class.derivatives(derivatives_data)
451 
452   data = nil if data.empty?
453 
454   super(data)
455 end
map_derivative(derivatives, **options, &block)

Iterates through nested derivatives and maps results.

attacher.map_derivative(derivatives) { |path, file| ... }
[show source]
    # File lib/shrine/plugins/derivatives.rb
483 def map_derivative(derivatives, **options, &block)
484   shrine_class.map_derivative(derivatives, **options, &block)
485 end
merge_derivatives(new_derivatives)

Deep merges given uploaded derivatives with current derivatives.

attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
attacher.merge_derivatives({ two: uploaded_file })
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
[show source]
    # File lib/shrine/plugins/derivatives.rb
303 def merge_derivatives(new_derivatives)
304   derivatives_synchronize do
305     merged_derivatives = deep_merge_derivatives(derivatives, new_derivatives)
306     set_derivatives(merged_derivatives)
307   end
308 end
process_derivatives(processor_name = :default, source = nil, **options)

Downloads the attached file and calls the specified processor.

Attacher.derivatives_processor :thumbnails do |original|
  processor = ImageProcessing::MiniMagick.source(original)

  {
    small:  processor.resize_to_limit!(300, 300),
    medium: processor.resize_to_limit!(500, 500),
    large:  processor.resize_to_limit!(800, 800),
  }
end

attacher.process_derivatives(:thumbnails)
#=> { small: #<File:...>, medium: #<File:...>, large: #<File:...> }
[show source]
    # File lib/shrine/plugins/derivatives.rb
278 def process_derivatives(processor_name = :default, source = nil, **options)
279   # handle receiving only source file without a processor
280   unless processor_name.respond_to?(:to_sym)
281     source         = processor_name
282     processor_name = :default
283   end
284 
285   source ||= file!
286 
287   processor_settings = self.class.derivatives_processor_settings(processor_name) || {}
288 
289   if processor_settings[:download]
290     shrine_class.with_file(source) do |file|
291       _process_derivatives(processor_name, file, **options)
292     end
293   else
294     _process_derivatives(processor_name, source, **options)
295   end
296 end
promote(**options)

In addition to promoting the main file, also promotes any cached derivatives. This is useful when these derivatives are being created as part of a direct upload.

attacher.assign(io)
attacher.add_derivative(:thumb, file, storage: :cache)
attacher.promote
attacher.stored?(attacher.derivatives[:thumb]) #=> true
[show source]
    # File lib/shrine/plugins/derivatives.rb
162 def promote(**options)
163   super
164   promote_derivatives
165   create_derivatives if create_derivatives_on_promote?
166 end
promote_derivatives(**options)

Uploads any cached derivatives to permanent storage.

[show source]
    # File lib/shrine/plugins/derivatives.rb
169 def promote_derivatives(**options)
170   stored_derivatives = map_derivative(derivatives) do |path, derivative|
171     if cached?(derivative)
172       upload_derivative(path, derivative, **options)
173     else
174       derivative
175     end
176   end
177 
178   set_derivatives(stored_derivatives) unless derivatives == stored_derivatives
179 end
remove_derivative(path, **options)

Removes derivative with specified name from the derivatives hash.

attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
attacher.remove_derivative(:one) #=> #<Shrine::UploadedFile> (removed derivative)
attacher.derivatives #=> { two: #<Shrine::UploadedFile> }

Nested derivatives are also supported:

attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
attacher.remove_derivative([:nested, :one]) #=> #<Shrine::UploadedFile> (removed derivative)
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }

The :delete option can be passed for deleting removed derivative:

attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
derivative = attacher.remove_derivatives(:two, delete: true)
derivative.exists? #=> false
[show source]
    # File lib/shrine/plugins/derivatives.rb
376 def remove_derivative(path, **options)
377   remove_derivatives(path, **options).first
378 end
remove_derivatives(*paths, delete: false)

Removes derivatives with specified name from the derivatives hash.

attacher.derivatives
#=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile>, three: #<Shrine::UploadedFile> }

attacher.remove_derivatives(:two, :three)
#=> [#<Shrine::UploadedFile>, #<Shrine::UploadedFile>] (removed derivatives)

attacher.derivatives
#=> { one: #<Shrine::UploadedFile> }

Nested derivatives are also supported:

attacher.derivatives
#=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile>, three: #<Shrine::UploadedFile> } }

attacher.remove_derivatives([:nested, :two], [:nested, :three])
#=> [#<Shrine::UploadedFile>, #<Shrine::UploadedFile>] (removed derivatives)

attacher.derivatives
#=> { nested: { one: #<Shrine::UploadedFile> } }

The :delete option can be passed for deleting removed derivatives:

attacher.derivatives
#=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile>, three: #<Shrine::UploadedFile> }

two, three = attacher.remove_derivatives(:two, :three, delete: true)

two.exists?   #=> false
three.exists? #=> false
[show source]
    # File lib/shrine/plugins/derivatives.rb
341 def remove_derivatives(*paths, delete: false)
342   removed_derivatives = paths.map do |path|
343     path = Array(path)
344 
345     if path.one?
346       derivatives.delete(path.first)
347     else
348       derivatives.dig(*path[0..-2]).delete(path[-1])
349     end
350   end
351 
352   set_derivatives derivatives
353 
354   delete_derivatives(removed_derivatives) if delete
355 
356   removed_derivatives
357 end
set_derivatives(derivatives)

Sets the given hash of uploaded files as derivatives.

attacher.set_derivatives({ thumb: uploaded_file })
attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
[show source]
    # File lib/shrine/plugins/derivatives.rb
392 def set_derivatives(derivatives)
393   self.derivatives = derivatives
394   set file # trigger model write
395   derivatives
396 end
upload_derivative(path, file, storage: nil, **options)

Uploads the given file and deletes it afterwards.

hash = attacher.upload_derivative(:thumb, thumb)
hash[:thumb] #=> #<Shrine::UploadedFile>
[show source]
    # File lib/shrine/plugins/derivatives.rb
254 def upload_derivative(path, file, storage: nil, **options)
255   path      = derivative_path(path)
256   storage ||= derivative_storage(path)
257 
258   file.open    if file.is_a?(Tempfile)       # refresh file descriptor
259   file.binmode if file.respond_to?(:binmode) # ensure binary mode
260 
261   upload(file, storage, derivative: path, delete: true, action: :derivatives, **options)
262 end
upload_derivatives(files, **options)

Uploads given hash of files.

hash = attacher.upload_derivatives({ thumb: thumb })
hash[:thumb] #=> #<Shrine::UploadedFile>
[show source]
    # File lib/shrine/plugins/derivatives.rb
244 def upload_derivatives(files, **options)
245   map_derivative(files) do |path, file|
246     upload_derivative(path, file, **options)
247   end
248 end
url(*path, **options)

Allows generating a URL to the derivative by passing the derivative name.

attacher.add_derivatives({ thumb: thumb })
attacher.url(:thumb) #=> "https://example.org/thumb.jpg"
[show source]
    # File lib/shrine/plugins/derivatives.rb
144 def url(*path, **options)
145   return super if path.empty?
146 
147   path = derivative_path(path)
148 
149   url   = derivatives.dig(*path)&.url(**options)
150   url ||= default_url(**options, derivative: path)
151   url
152 end