123456789_123456789_123456789_123456789_123456789_

Class: ActiveStorage::Previewer

Relationships & Source Files
Namespace Children
Classes:
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 20

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 16

def self.accept?(blob)
  false
end

Instance Attribute Details

#blob (readonly)

[ GitHub ]

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

attr_reader :blob

Instance Method Details

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

[ GitHub ]

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

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

  open_tempfile do |err|
    IO.popen(argv, in: IO::NULL, 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. See ActiveStorage::Blob#open for details.

[ GitHub ]

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

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 53

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 73

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 97

def logger # :doc:
  ActiveStorage.logger
end

#open_tempfile (private)

[ GitHub ]

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

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 27

def preview(**options)
  raise NotImplementedError
end

#service_name (private)

[ GitHub ]

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

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 101

def tmpdir # :doc:
  Dir.tmpdir
end