Class: FilePipeline::FileOperations::FileOperation

Inherits:
Object
  • Object
show all
Defined in:
lib/file_pipeline/file_operations/file_operation.rb

Overview

This is an abstract class to be subclassed when file operations are implemented.

For the autoloading mechanism in FilePipeline.load to work, it is required that subclasses are in defined in the module FilePipeline::FileOperations.

The constructor (#initialze) must accept a doublesplat argument as the only argument and should call super.

Subclasses must implement an #operation method or override the #run method.

If the operation results in file type different than that of the file that is passed to #run or #operation as src_file, the subclass must have a #target_extension method that returns the appropriate extension.

If the operation is non-modifying, the subclass must redefine the #modifies? methods to return false.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts, defaults = {}) ⇒ FileOperation

Returns a new instance and sets #options.

This can be called from subclasses.

Arguments
  • defaults - Default options for the subclass (hash).

  • opts - Options passed to the sublass initializer (hash).



36
37
38
39
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 36

def initialize(opts, defaults = {})
  opts.transform_keys!(&:to_sym)
  @options = defaults.update(opts)
end

Instance Attribute Details

#optionsObject (readonly)

A Hash; any options used when performing #operation.



26
27
28
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 26

def options
  @options
end

Instance Method Details

#captured_data_tagObject

Returns the NO_DATA tag.

If the results returned by a subclass contain data, override this methos to return the appropriate tag for the data. This tag can be used to filter data captured by operations.

Tags are defined in CapturedDataTags.



48
49
50
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 48

def captured_data_tag
  CapturedDataTags::NO_DATA
end

#extension(file) ⇒ Object

Returns the extension for file (a string). This should be the extension for the type the file created by #operation will have.

If the #operation of a subclass will result in a different extension of predictable type, define a #target_extension method.



57
58
59
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 57

def extension(file)
  target_extension || File.extname(file)
end

#failure(log_data = nil) ⇒ Object

Returns a Results object with the Results#success set to false and any information returned by the operation in log_data (a string error, array, or hash).



64
65
66
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 64

def failure(log_data = nil)
  results false, log_data
end

#modifies?Boolean

Returns true if the FIleOperation will create a new version. Default: true.

Returns:

  • (Boolean)


70
71
72
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 70

def modifies?
  true
end

#nameObject

Returns the class name (string) of self without the names of the modules that the class is nested in.



76
77
78
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 76

def name
  self.class.name.split('::').last
end

#operation(*_) ⇒ Object

:args: src_file, out_file, original = nil

To be implemented in subclasses. Should return any logged errors or data produced (a string, error, array, or hash) or nil.

Arguments
  • src_file - Path for the file the operation will use as the basis for the new version it will create.

  • out_file - Path the file created by the operation will be written to.

  • original - Path to the original, unmodified, file (optional).



92
93
94
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 92

def operation(*_)
  raise 'not implemented'
end

#results(success, log_data = nil) ⇒ Object

Returns a new Results object with the #descrip1tion of self, success, and any information returned by the operation as log_data (a string, error, array, or hash.)

Examples
error = StandardError.new
warning = 'a warning occurred'
log = [error, warning]
data = { mime_type: 'image/jpeg' }

my_op = MyOperation.new

my_op.results(false, error)
# => <Results @data=nil, @log=[error], ..., @success=false>

my_op.results(true, warning)
# => <Results @data=nil, @log=[warning], ..., @success=true>

my_op.results(true, data)
# => <Results @data=data, @log=[], ..., @success=true>

my_op.results(true, [warning, data])
# => <Results @data=data, @log=[warning], ..., @success=true>

my_op.results(false, log)
# => <Results @data=nil, @log=[error, warning], ..., @success=false>

my_op.results(false, [log, data])
# => <Results @data=data, @log=[error, warning], ..., @success=false>


127
128
129
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 127

def results(success, log_data = nil)
  Results.new(self, success, log_data)
end

#run(src_file, directory, original = nil) ⇒ Object

Runs the operation on src_file and retunes an array with a path for the file created by the operation and a Results object.

Subclasses of FileOperation must either implement an #operation method, or override the #run method, making sure it has the same signature and kind of return value.

The method will create a new path for the file produced by #operation to be written to. This path will consist of directory and a new basename.

The optional original argument can be used to reference another file, e.g. when exif metadata tags missing in the src_file are to be copied over from another file.



144
145
146
147
148
149
150
151
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 144

def run(src_file, directory, original = nil)
  out_file = target directory, extension(src_file) if modifies?
  log_data = operation src_file, out_file, original
  [out_file, success(log_data)]
rescue StandardError => e
  FileUtils.rm out_file if out_file && File.exist?(out_file)
  [out_file, failure(e)]
end

#success(log_data = nil) ⇒ Object

Returns a Results object with the Results#success set to true and any information returned by the operation in log_data (a string error, array, or hash).



156
157
158
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 156

def success(log_data = nil)
  results true, log_data
end

#target(directory, extension, kind = :timestamp) ⇒ Object

Returns a new path to which the file created by the operation can be written. The path will be in directory, with a new basename determined by kind and have the specified file extension.

There are two options for the kind of basename to be created:

  • :timestamp (default) - Creates a timestamp basename.

  • :random - Creates a UUID basename.

The timestamp format is YYYY-MM-DDTHH:MM:SS.NNNNNNNNN.

Examples
file_operation.target('path/to/dir', '.png', :timestamp)
# => 'path/to/dir/2019-07-24T09:30:12:638935761.png'

file_operation.target('path/to/dir', '.png', :random)
# => 'path/to/dir/123e4567-e89b-12d3-a456-426655440000.png'


177
178
179
180
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 177

def target(directory, extension, kind = :timestamp)
  filename = FilePipeline.new_basename(kind) + extension
  File.join directory, filename
end

#target_extensionObject

Returns nil.

If the #operation of a subclass will result in a different extension of predictable type, override this method to return the appropriate type.

If, for instance, the operation will always create a TIFF file, the implementation could be:

# Returns '.tiff'
def target_extension
  '.tiff'
end


195
# File 'lib/file_pipeline/file_operations/file_operation.rb', line 195

def target_extension; end