123456789_123456789_123456789_123456789_123456789_

Class: ActiveStorage::Previewer

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Subclasses:
Inherits: Object
Defined in: activestorage/lib/active_storage/previewer.rb

Overview

This is an abstract base class for previewers, which generate images from blobs. See MuPDFPreviewer and VideoPreviewer for examples of concrete subclasses.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(blob) ⇒ Previewer

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 18

def initialize(blob)
  @blob = blob
end

Class Method Details

.accept?(blob) ⇒ Boolean

Implement this method in a concrete subclass. Have it return true when given a blob from which the previewer can generate an image.

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 14

def self.accept?(blob)
  false
end

Instance Attribute Details

#blob (readonly)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 10

attr_reader :blob

Instance Method Details

#capture(*argv, to:) (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 78

def capture(*argv, to:)
  to.binmode

  open_tempfile do |err|
    IO.popen(argv, err: err) { |out| IO.copy_stream(out, to) }
    err.rewind

    unless $?.success?
      raise PreviewError, "#{argv.first} failed (status #{$?.exitstatus}): #{err.read.to_s.chomp}"
    end
  end

  to.rewind
end

#download_blob_to_tempfile(&block) (private)

Downloads the blob to a tempfile on disk. Yields the tempfile.

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 31

def download_blob_to_tempfile(&block) # :doc:
  blob.open tmpdir: tmpdir, &block
end

#draw(*argv) (private)

Executes a system command, capturing its binary output in a tempfile. Yields the tempfile.

Use this method to shell out to a system library (e.g. muPDF or FFmpeg) for preview image generation. The resulting tempfile can be used as the :io value in an attachable ::Hash:

def preview
  download_blob_to_tempfile do |input|
    draw "my-drawing-command", input.path, "--format", "png", "-" do |output|
      yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png"
    end
  end
end

The output tempfile is opened in the directory returned by #tmpdir.

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 49

def draw(*argv) # :doc:
  open_tempfile do |file|
    instrument :preview, key: blob.key do
      capture(*argv, to: file)
    end

    yield file
  end
end

#instrument(operation, payload = {}, &block) (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 69

def instrument(operation, payload = {}, &block)
  ActiveSupport::Notifications.instrument "#{operation}.active_storage", payload.merge(service: service_name), &block
end

#logger (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 93

def logger # :doc:
  ActiveStorage.logger
end

#open_tempfile (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 59

def open_tempfile
  tempfile = Tempfile.open("ActiveStorage-", tmpdir)

  begin
    yield tempfile
  ensure
    tempfile.close!
  end
end

#preview(**options)

Override this method in a concrete subclass. Have it yield an attachable preview image (i.e. anything accepted by Attached::One#attach). Pass the additional options to the underlying blob that is created.

Raises:

  • (NotImplementedError)
[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 25

def preview(**options)
  raise NotImplementedError
end

#service_name (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 73

def service_name
  # ActiveStorage::Service::DiskService => Disk
  blob.service.class.to_s.split("::").third.remove("Service")
end

#tmpdir (private)

[ GitHub ]

  
# File 'activestorage/lib/active_storage/previewer.rb', line 97

def tmpdir # :doc:
  Dir.tmpdir
end