Class: FilePipeline::VersionedFile
- Inherits:
-
Object
- Object
- FilePipeline::VersionedFile
- Extended by:
- Forwardable
- Includes:
- FileOperations::ExifManipulable
- Defined in:
- lib/file_pipeline/versioned_file.rb
Overview
VersionedFile creates a directory where it stores any versions of file.
Instance Attribute Summary collapse
-
#basename ⇒ Object
readonly
The basename of the versioned file.
-
#history ⇒ Object
readonly
A hash with file paths as keys, information on the modifications applied to create the version as values (instances of FileOperations::Results).
-
#original ⇒ Object
readonly
The path to the original file of self.
-
#target_suffix ⇒ Object
readonly
A String that is appended to the file basename when the file written by #finalize is not replacing the original.
Instance Method Summary collapse
-
#<<(version_info) ⇒ Object
Adds a new version to #history and returns self.
-
#changed? ⇒ Boolean
Returns
true
if there are #versions (file has been modified). -
#clone ⇒ Object
(also: #touch)
Creates a new identical version of #current.
-
#current ⇒ Object
Returns the path to the current file or the #original if no versions have been created.
-
#current_extension ⇒ Object
Returns the file extension for the #current file.
-
#directory ⇒ Object
Returns the path to the directory where the versioned of
self
are stored. -
#finalize(overwrite: false) ⇒ Object
Writes the #current version to #basename, optionally the #target_suffix, and the #current_extension in #original_dir.
-
#initialize(file, target_suffix: SecureRandom.hex(4)) ⇒ VersionedFile
constructor
Returns a new instance with
file
as the #original. -
#metadata(for_version: :current) ⇒ Object
Returns the Exif metadata.
-
#modify ⇒ Object
Creates a new version.
-
#original_dir ⇒ Object
Returns the directory where #original is stored.
-
#recovered_metadata ⇒ Object
Returns a hash into which all captured data from file operations with the FileOperations::CapturedDataTags::DROPPED_EXIF_DATA has been merged.
Methods included from FileOperations::ExifManipulable
#delete_tags, file_tags, #missing_exif_fields, #parse_exif_errors, parse_tag_error, #read_exif, strip_path, #write_exif
Constructor Details
#initialize(file, target_suffix: SecureRandom.hex(4)) ⇒ VersionedFile
Returns a new instance with file
as the #original.
Arguments
-
file
- Path to the file the instance will be based on. That file should not be touched unless #finalize is called with the:overwrite
option set totrue
.
Caveat it can not be ruled out that buggy or malignant file operations modify the original.
Options
<tt>target_suffix</ttm> is a string to be appended to the file that will be written by #finalize (the last version) if #finalize is to preserve the original. It is recommended to use a randomized string (default) to avoid clashes with other files in the directory.
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/file_pipeline/versioned_file.rb', line 68 def initialize(file, target_suffix: SecureRandom.hex(4)) raise Errors::MissingVersionFileError, file: file unless File.exist? file @original = file @basename = File.basename(file, '.*') @history = Versions::History.new @directory = nil @target_suffix = target_suffix history[original] = nil end |
Instance Attribute Details
#basename ⇒ Object (readonly)
The basename of the versioned file.
9 10 11 |
# File 'lib/file_pipeline/versioned_file.rb', line 9 def basename @basename end |
#history ⇒ Object (readonly)
A hash with file paths as keys, information on the modifications applied to create the version as values (instances of FileOperations::Results).
13 14 15 |
# File 'lib/file_pipeline/versioned_file.rb', line 13 def history @history end |
#original ⇒ Object (readonly)
The path to the original file of self.
16 17 18 |
# File 'lib/file_pipeline/versioned_file.rb', line 16 def original @original end |
#target_suffix ⇒ Object (readonly)
A String that is appended to the file basename when the file written by #finalize is not replacing the original.
20 21 22 |
# File 'lib/file_pipeline/versioned_file.rb', line 20 def target_suffix @target_suffix end |
Instance Method Details
#<<(version_info) ⇒ Object
Adds a new version to #history and returns self.
version_info
must be a path to an existing file or an array with the path and optionally a FileOperations::Results instance: ['path/to/file', results_object]
. Will move the file to #directory if it is in another directory.
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/file_pipeline/versioned_file.rb', line 85 def <<(version_info) file, info = version_info if info&.failure raise Errors::FailedModificationError, info: info, file: original end version = validate(file) @history[version] = info self rescue StandardError => e reset raise e end |
#changed? ⇒ Boolean
Returns true
if there are #versions (file has been modified).
Warning: It will also return true
if the file has been cloned.
102 103 104 |
# File 'lib/file_pipeline/versioned_file.rb', line 102 def changed? current != original end |
#clone ⇒ Object Also known as: touch
Creates a new identical version of #current. Will only add the path of the file to history, but no FileOperations::Results.
108 109 110 111 112 |
# File 'lib/file_pipeline/versioned_file.rb', line 108 def clone filename = FilePipeline.new_basename + current_extension clone_file = Versions.copy(current, directory, filename) self << clone_file end |
#current ⇒ Object
Returns the path to the current file or the #original if no versions have been created.
116 117 118 |
# File 'lib/file_pipeline/versioned_file.rb', line 116 def current versions.last || original end |
#current_extension ⇒ Object
Returns the file extension for the #current file.
121 122 123 |
# File 'lib/file_pipeline/versioned_file.rb', line 121 def current_extension File.extname current end |
#directory ⇒ Object
Returns the path to the directory where the versioned of self
are stored. Creates the directory if it does not exist.
127 128 129 |
# File 'lib/file_pipeline/versioned_file.rb', line 127 def directory @directory ||= workdir end |
#finalize(overwrite: false) ⇒ Object
Writes the #current version to #basename, optionally the #target_suffix, and the #current_extension in #original_dir. Deletes all versions and resets the #history to an empty Hash. Returns the path to the written file.
If the optional block is passed, it will be evaluated before the file is finalized.
Options
-
overwrite
-true
orfalse
-
false
(default) - The #target_suffix will be appended to the #basename and the #original will be preserved. -
true
- The finalized version will replace the #original.
-
145 146 147 148 149 150 151 152 |
# File 'lib/file_pipeline/versioned_file.rb', line 145 def finalize(overwrite: false) yield(self) if block_given? filename = overwrite ? replacing_trarget : preserving_taget FileUtils.rm original if overwrite @original = Versions.copy(current, original_dir, filename) ensure reset end |
#metadata(for_version: :current) ⇒ Object
Returns the Exif metadata
Options
-
:for_version
-current
ororiginal
-
current
(default) - Metadata for the #current file will be returned. -
original
- Metadata for the #original file will be returned.
-
– TODO: when file is not an image file, this should return other metadata than exif. ++
167 168 169 170 171 172 173 |
# File 'lib/file_pipeline/versioned_file.rb', line 167 def (for_version: :current) if %i[current original].include? for_version file = public_send(for_version) end file ||= for_version read_exif(file).first end |
#modify ⇒ Object
Creates a new version. Requires a block that must return a path to an existing file or an array with the path and optionally a FileOperations::Results instance: ['path/to/file', results_object]
.
The actual file modification logic will be in the block.
The block must take three arguments: for the #current file (from which the modified version will be created), the work #directory (to where the modified file will be written), and the #original file (which will only be used in modifications that need the original file for reference, such as modifications that restore file metadata that was lost in other modifications).
188 189 190 |
# File 'lib/file_pipeline/versioned_file.rb', line 188 def modify self << yield(current, directory, original) end |
#original_dir ⇒ Object
Returns the directory where #original is stored.
193 194 195 |
# File 'lib/file_pipeline/versioned_file.rb', line 193 def original_dir File.dirname original end |
#recovered_metadata ⇒ Object
Returns a hash into which all captured data from file operations with the FileOperations::CapturedDataTags::DROPPED_EXIF_DATA has been merged.
199 200 201 202 203 204 |
# File 'lib/file_pipeline/versioned_file.rb', line 199 def return unless changed? captured_data_with(FileOperations::CapturedDataTags::DROPPED_EXIF_DATA) &.reduce({}) { |recovered, data| recovered.merge data } end |